xml 解析有三种,分别是SAX,PULL,DOM
用到的xml如下:
<apps>
<app>
<id>1id>
<name>Google mapsname>
<version>1.0version>
app>
<app>
<id>2id>
<name>chromename>
<version>2.1version>
app>
<app>
<id>3id>
<name>google playname>
<version>3.1version>
app>
apps>
SAX(Simple API For XML)是以流式的处理方式解析的,不记录所读的内容信息,是一种以事件驱动的XML API。主要对文档进行顺序扫描,当扫描到文档的开始和结束,元素的开始和结束时通知事件处理函数,由事件处理函数做相对应的操作,然后继续扫描,直到文档的结束。解析度快,占用内存少,非常适用使在Andoid移动设备中使用
使用步骤:
1. 新建 ContentHanlder 类继承 DefaultHandler 类,并重写父类的五个方法
startDocument(): 开始解析XML时调用
startElement(): 开始解析某个结点时调用
characters(): 在获取节点内容时调用
endElement(): 在完成解析某个结点时调用
endDocument(): 在完成整个XML解析的时候调用
2.创建函数 parseXMLWithSAX
3.调用函数 parseXMLWithSAX 解析 XML
我把使用到的xml文件放到assets文件夹下
import android.util.Log;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/**
* Created by RainBowAndStar on 2018/4/3.
*/
public class ContentHandler extends DefaultHandler {
private String nodeName;
private StringBuilder id;
private StringBuilder name;
private StringBuilder version;
private String TAG = "SAX";
//开始解析 XML 文档,一般做初始化操作
@Override
public void startDocument() throws SAXException {
id = new StringBuilder();
name = new StringBuilder();
version = new StringBuilder();
}
//开始解析结点
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
//localName 记录当前结点的名字
nodeName = localName;
}
//开始提取结点中内容
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
if("id".equals(nodeName))
id.append(ch,start,length);
else if("name".equals(nodeName))
name.append(ch,start,length);
else if("version".equals(nodeName))
version.append(ch,start, length);
}
//结束结点解析
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if("app".equals(localName)){
//可能包含回车或换行符
Log.d(TAG, "endElement: "+nodeName);
Log.d(TAG, "endElement: id = " + id.toString().trim());
Log.d(TAG, "endElement: name = "+ name.toString().trim());
Log.d(TAG, "endElement: version = "+ version.toString().trim());
//打印结束后清空,否则会影响下一次内容的读取
id.setLength(0);
name.setLength(0);
version.setLength(0);
}
}
//结束XML文档解析
@Override
public void endDocument() throws SAXException {
Log.e(TAG, "endDocument: 文档结束" );
}
}
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import javax.xml.parsers.SAXParserFactory;
import linxin.www.test.sax.ContentHandler;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getData();
}
private void getData() {
StringBuffer sb = new StringBuffer();
try {
InputStream inputStream= getAssets().open("TestXML");
byte[] bytes = new byte[1024];
if(inputStream.read(bytes)!= 0 ){
sb.append(new String (bytes,0,bytes.length));
}
} catch (IOException e) {
e.printStackTrace();
}
paraseXMLWithSAX(sb.toString().trim());
}
//TODO 用SAX方式解析XML
private void paraseXMLWithSAX(String xmlData){
Log.d("SAX", "paraseXMLWithSAX: "+xmlData);
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
XMLReader reader = factory.newSAXParser().getXMLReader();
ContentHandler handler = new ContentHandler();
//将contentHandler的实例设置到XMLReader中
reader.setContentHandler(handler);
//开始解析
InputSource is = new InputSource(new StringReader(xmlData));
is.setEncoding("ISO-8859-15");
reader.parse(is);
}catch(Exception e){
e.printStackTrace();
}
}
}
PULL解析器的运行方式和SAX类似,都是基于事件的模式。不同的是,在PULL解析过程中返回的是数字,且我们需要自己获取产生的事件然后做相应的操作,而不像SAX那样由处理器触发一种事件的方法,执行我们的代码。
**解析过程:**XML pull提供了开始元素和结束元素。当某个元素开始时,我们可以调用parser.nextText从XML文档中提取所有字符数据。当解释到一个文档结束时,自动生成EndDocument事件。
读取到xml的声明返回 START_DOCUMENT;
读取到xml的开始标签返回 START_TAG
读取到xml的文本返回 T XT
取到xml的结束标签返回 END_TAG
读取到xml的结束返回 END_ DOCUMENT
package linxin.www.test;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getData();
}
private void getData() {
StringBuffer sb = new StringBuffer();
try {
InputStream inputStream= getAssets().open("TestXML");
byte[] bytes = new byte[1024];
if(inputStream.read(bytes)!= 0 ){
sb.append(new String (bytes,0,bytes.length));
}
} catch (IOException e) {
e.printStackTrace();
}
parseXMLWithPull(sb.toString().trim());
}
//TODO 用Pull方式解析XML
private void parseXMLWithPull(String xmlData){
String TAG ="PULL";
try {
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
XmlPullParser xmlPullParser = factory.newPullParser();
//设置输入的内容
xmlPullParser.setInput(new StringReader(xmlData));
//获取当前解析事件,返回的是数字
int eventType = xmlPullParser.getEventType();
//保存内容
String id = "";
String name = "";
String version="";
while (eventType != (XmlPullParser.END_DOCUMENT)){
String nodeName = xmlPullParser.getName();
switch (eventType){
//开始解析XML
case XmlPullParser.START_TAG:{
//nextText()用于获取结点内的具体内容
if("id".equals(nodeName))
id = xmlPullParser.nextText();
else if("name".equals(nodeName))
name = xmlPullParser.nextText();
else if("version".equals(nodeName))
version = xmlPullParser.nextText();
} break;
//结束解析
case XmlPullParser.END_TAG:{
if("app".equals(nodeName)){
Log.d(TAG, "parseXMLWithPull: id is "+ id);
Log.d(TAG, "parseXMLWithPull: name is "+ name);
Log.d(TAG, "parseXMLWithPull: version is "+ version);
}
} break;
default: break;
}
//下一个
eventType = xmlPllParser.next();
}
} catch (Excetion e) {
e.printStackTrace();
}
}
}
DOM,即对象文档模型,它是将整个XML文档载入内存(所以效率较低,不推荐使用),每一个节点当做一个对象,结合代码分析。DOM实现时首先为XML文档的解析定义一组接口,解析器读入整个文档,然后构造一个驻留内存的树结构,这样代码就可以使用DOM接口来操作整个树结构。 由于DOM在内存中以树形结构存放,因此检索和更新效率会更高。但是对于特别大的文档,解析和加载整个文档将会很耗资源。 当然,如果XML文件的内容比较小,采用DOM是可行的。
工作原理:使用DOM对XML文件进行操作时,首先要解析文件,将文件分为独立的元素、属性和注释等,然后以节点树的形式在内存中对XML文件进行表示,就可以通过节点树访问文档的内容,并根据需要修改文档。
使用步骤:
采用DOM解析时具体处理步骤是:
首先利用DocumentBuilderFactory创建一个DocumentBuilderFactory实例
然后利用DocumentBuilderFactory创建DocumentBuilder
然后加载XML文档(Document)
然后获取文档的根结点(Element)
,
然后获取根结列表(NodeList),
然后使用再获取子节点列表中的需要读取的结点。,
/**
* Created by RainBowAndStar on 2018/4/4.
*/
public class App {
private String id = null ;
private String name = null;
private String version = null;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
}
import android.content.Context;
import android.util.Log;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import java.util.ArrayList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
/**
* Created by RainBowAndStar on 2018/4/4.
*/
public class DomHelper {
public static ArrayList queryXML(Context context)
{
ArrayList apps = new ArrayList();
try {
//①获得DOM解析器的工厂示例:
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
//②从Dom工厂中获得dom解析器
DocumentBuilder dbBuilder = dbFactory.newDocumentBuilder();
//③把要解析的xml文件读入Dom解析器
Document doc = dbBuilder.parse(context.getAssets().open("TestXML"));
System.out.println("处理该文档的DomImplemention对象=" + doc.getImplementation());
//④得到文档中名称为apps的元素的结点列表
NodeList nList = doc.getElementsByTagName("app"); //TODO 这里不用一层层获取,不用获取到apps然后再获取app
//⑤遍历该集合,显示集合中的元素以及子元素的名字
for(int i = 0;i < nList.getLength();i++)
{
//先从元素开始解析
Element personElement = (Element) nList.item(i);
App app = new App();
// app.setId(Integer.valueOf(personElement.getAttribute("id")));
//获取person下的name和age的Note集合
NodeList childNoList = personElement.getChildNodes(); //3
for(int j = 0;j < childNoList.getLength();j++)
{
Node childNode = childNoList.item(j);
//判断子note类型是否为元素Note
if(childNode.getNodeType() == Node.ELEMENT_NODE)
{
Element childElement = (Element) childNode;
if("id".equals(childElement.getNodeName()))
app.setId(childElement.getFirstChild().getNodeValue());
else if("name".equals(childElement.getNodeName()))
app.setName(childElement.getFirstChild().getNodeValue());
else if("version".equals(childElement.getNodeName())){
app.setVersion(childElement.getFirstChild().getNodeValue());
}
}
}
apps.add(app);
}
} catch (Exception e) {
e.printStackTrace();
}
for(int k = 0 ;k
Log.d("Dom",apps.get(k).getId()
);
Log.d("Dom",apps.get(k).getName());
Log.d("Dom",apps.get(k).getVersion());
}
return apps;
}
}
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DomHelper.queryXML(this);
}
}
参考文章: https://www.cnblogs.com/guolingyun/p/6148462.html