Android平台上解析XML文件的方法有三种。
Simple API for XML)
基于 事件驱动 的解析器, 它 并不需要解析完整个文档,在按内容顺序(不可倒退)解析文档的过程中,SAX会判断当前读到的字符是否合法XML语法中的某部分,如果符合就会触发事件, 调用事件处理器相应的处理方法 。
需要重写DefaultHandler的几个方法,
startDocument()//文档开始,做好准备
startElement(String uri, String localName, String qName, Attributes attributes)
characters(char[] ch, int start, int length)//处理文本内容
endElement(String uri, String localName, String qName)
当执行文档时遇到起始节点,startElement方法将会被调用,我们可以获取起始节点相关信息;然后characters方法被调用,我们可以获取节点内的文本信息;最后endElement方法被调用,我们可以做收尾的相关操作。
Document Object Model)
基于树形结构的的节点或信息片段的集合, DOM解析XML文件时会将XML文件的所有内容读取到内存中,然后使用DOM API遍历XML树、检索所需数据。利用DOM中的对象,可以对XML文档进行读取、搜索、修改、添加和删除等操作。
使用DOM操作XML的代码看起来比较直观,并且 由于 XML所有内容都 在内存中以树形结构存放,因此检索和更新效率会更高, 但同时内存的消耗比较大,除非需要编辑XML文件或者XML树结构复杂否则不建议使用。
/*
<?xml version="1.0" encoding="UTF-8"?>
<persons>
<person id="23">
<name>李明</name>
<age>30</age>
</person>
<person id="20">
<name>李向梅</name>
<age>25</age>
</person>
</persons>*/
public static List<Person> readXML(InputStream inStream) {
List<Person> persons = new ArrayList<Person>();//设定person实体类有id和name,age
try {
//取得DocumentBuilderFactory实例
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
//从factory获取DocumentBuilder实例
DocumentBuilder builder = factory.newDocumentBuilder();
Document dom = builder.parse(inStream);//解析输入流 得到Document实例
Element root = dom.getDocumentElement();//得到节点树
NodeList items = root.getElementsByTagName("person");//查找所有person节点
for (int i = 0; i < items.getLength(); i++) {
Person person = new Person();
Element personNode = (Element) items.item(i);//得到第一个person节点
person.setId(new Integer(personNode.getAttribute("id")));//获取person节点的id属性值
//获取person节点下的所有子节点(标签之间的空白节点和name/age元素)
NodeList childsNodes = personNode.getChildNodes();
for (int j = 0; j < childsNodes.getLength(); j++) {
Node node = (Node) childsNodes.item(j);
if(node.getNodeType() == Node.ELEMENT_NODE){//判断是否为元素类型
Element childNode = (Element) node;
if ("name".equals(childNode.getNodeName())){ //判断是否name元素
//获取name元素下Text节点,然后从Text节点获取或者更新数据,这里只要获胜即可
person.setName(childNode.getFirstChild().getNodeValue());
}
else if (“age”.equals(childNode.getNodeName())) {
person.setAge(new Short(childNode.getFirstChild().getNodeValue()));
}
}
}
persons.add(person);
}
inStream.close();
} catch (Exception e) {
e.printStackTrace();
}
return persons;
}
PULL解析
它提供了如开始元素和结束元素等事件( 读取到xml的声明返回START_DOCUMENT;
读取到xml的结束返回END_DOCUMENT,读取到xml的开始标签返回START_TAG,读取到xml的结束标签返回END_TAG,
读取到xml的文本返回TEXT
)
在PULL解析过程中, 使用parser.next()迭代遍历 节点元素并触发相应事件并产生 事件标志(数字),我们可以通过 switch对感兴趣的事件进行处理。
public static List<Person> readXML(InputStream inStream) {
try {
XmlPullParser parser = Xml.newPullParser();//由android.util.Xml创建一个XmlPullParser实例
parser.setInput(inStream, "UTF-8");//设置输入流 并指明编码方式
Person currentPerson = null;
List<Person> persons = null;
int eventType = parser.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
switch (eventType) {
case XmlPullParser.START_DOCUMENT://文档开始事件,可以进行数据初始化处理
persons = new ArrayList<Person>();
break;
case XmlPullParser.START_TAG://开始元素事件
String name = parser.getName();
if (name.equalsIgnoreCase("person")) {
currentPerson = new Person();
currentPerson.setId(new Integer(parser.getAttributeValue(null, "id")));//获取属性值
} else if (currentPerson != null) {
if (name.equalsIgnoreCase("name")) {
currentPerson.setName(parser.nextText());// 如果后面是Text元素,即返回它的值
} else if (name.equalsIgnoreCase("age")) {
currentPerson.setAge(new Short(parser.nextText()));
}
}
break;
case XmlPullParser.END_TAG://结束元素事件
if (parser.getName().equalsIgnoreCase("person") && currentPerson != null) {
persons.add(currentPerson);
currentPerson = null;
}
break;
}
eventType = parser.next();
}
inStream.close();
return persons;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
总结
除非需要编辑XML文件或者XML树结构复杂否则不建议使用DOM解析。
SAX解析器的工作方式是自动将事件推入事件处理器进行处理,因此不能控制事件的处理主动结束;
而Pull解析器的工作方式为允许你的应用程序代码主动从解析器中获取事件,正因为是主动获取事件,因此可以在满足了需要的条件后不再获取事件,结束解析。Pull解析的过程
是一个while循环,随时可以跳出,而
SAX解析
不是,sax是只要解析了,就必须解析完成,要停只能靠抛
SAXException异常了。。
总之推荐用Pull解析,毕竟Android系统内部也是用的PULL解析器 解析各种XML的 。