android xml解析XmlPullParser的使用

xml相关参考  
xml规范: http://www.w3.org/TR/REC-xml/  
Xerces-J sax解析器的一篇教程: http://terpconnect.umd.edu/~zhangx/xml/html/xmlprog/xercessax/briefintro.html  

xml的组成:  
xml声明  
 
version:xml的版本,一般都是1.0 
encoding:xml的使用的编码,一般都是UTF-8 
standalone:表示该文档是否依赖于其他的文档(即是否include了其他的文档)。include了就是no,没有时就是yes(默认是没有的)。 

DOCTYPE声明  
 
文档声明引用的是文件时(这里就是DTDs/yuan.dtd)(相对路径、绝对路径或由url标识指定的文件)就使用SYSTEM关键字 


"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
文档声明引用的是文档标识符时(由公共组织定义的公认的标识符,如W3C定义的),就使用PUBLIC关键字。 

这边还在文档标识符后加了url标识的dtd文件,就是在文档标识符无法识别时备用的。 

processing instruction  
 
xml样式表指令。这里不做具体的介绍,只是知道下processing instruction在xml中是这么个东西。看api时也好理解一些。 

xml元素(就是经常看到的标签)。  
如在html中经常看到的就是: 
// 仅有名称的标签 

// 自关闭标签 
// 带有属性的标签 

文本内容  
就是在根标签内间的文本内容。(xml规范规定xml的内容必须在根标签内) 
如: 
 
text1 
    text2 
     
        text3 
     
 

entity reference实体引用  
在配置java环境变量时,就有一个类似的实体引用。比如我们会配置:JAVA_HOME:c:\java\jdk1.6.20,然后在path变量中加入:%JAVA_HOME%\bin;。这就是一个实体引用,就是把JAVA_HOME处的值替换过来。 

xml中的实体引用的语法是:&[实体名];(windows的环境变量中的语法是%[实体名]%)。xml中也预定义了几个可被引用的实体名:就是lt(<), gt(>), amp(&), quot("), apos(')。 

CDATA section  
xml规范中规定,这部分的内容不需要(解析器)做任何的处理,就按它原来的内容显示。只要将这部分的内容需要放入中就可以了。 
< > & ]]> 里面的内容不会被进行任何的处理。 

注释  
xml中使用来注释内容。 
如: 


xml中的相关术语:  
dtd、schema:  
两种文档约束语言,是用来写xml文档规则的。就是通过它们可以规定一个xml中可以使用哪些标签,哪些标签分别有哪些属性,哪个标签可以出现在哪个标签内部等一系列的规则。 

well-formed: 遵守xml规范的xml文档就是well-formed的。 
valid: 遵守dtd、schema约束的就是valid的。 

命名空间:  
命名空间的作用是用来区别有着相同名字,但却具有不同功能的东西。和编程语言的命名空间应该是差不多的功能。比如:同样的叫XmlParser,可能一个是来自java标准库的javax.xml.XmlParser(仅仅是举例);另一个是来自apache的(org.apache.XmlParser)。 
xml规范规定,需要使用一个唯一的URI和其缩写来指定命名空间。同时,每个xml文档都具有一个默认的命名空间(即不指定时) 

// 默认命名空间的一个元素 

    xmlns:java="http://yuanzhifei89.iteye.com/javax/xml" 
    xmlns:apache="http://yuanzhifei89.iteye.com/org/apache"> 
        // java命名空间的解析器去解析该xml 
        d:\file.xml 

        // apache命名空间的解析器去解析该xml 
        d:\file.xml 
 

推式解析器和拉式解析器  
推式解析器是一种主动类型的解析器,它在解析xml的过程中,会将解析到的东西主动的推送给我们。比如,在解析到
这种时,它就会发给我们一个startTag的事件;同时整个解析过程都是全自动的(即必须从xml开始到xml结束)。 

拉式解析器与其相对,是一种被动的解析器,我们想要什么东西得向它去请求才行。比如,我们想要
这种时,必须不断的去next()来找到该事件;同时它的整个解析过程是被动的,我们想解析到哪就解析到哪。 



专为JavaME等移动设备设计的解析api  
该部分api主要在org.xmlpull.v1包下,主要有以下几个类或接口: 
XmlPullParser:该接口定义了XMLPULL V1 API中需要的解析功能。 
XmlSerializer:该接口定义了序列化xml的需要的方法。 

XmlPullParserFactory:Xml解析器工厂类。一般都是用该工厂来创建解析器实例,这样在需要时切换为想要的解析器实现类。 
XmlPullParserException:不需多解释,异常最好理解。在解析过程中遇到非正常情况就会抛出该异常。 

使用XmlPullParser解析xml  
XmlPullParser是一种拉式解析器,所有的事件必须我们自己去请求。 

当我们不断的请求XmlPullParser事件时,会获取到的事件类型  
DOCDECL 
读到document type declaration时(就是

PROCESSING_INSTRUCTION 
处理指令。看上面的xml组成中有介绍什么是处理指令。 

CDSECT 
读到CDATA Section就报告该事件 

COMMENT 
读到注释时就报告该事件 

IGNORABLE_WHITESPACE 
可忽略的空白。在没用dtd约束文档时,IGNORABLE_WHITESPACE只会出现在根元素外面;对于有dtd约束的文档,空白由dtd约束文档定义。(dtd约束文档就是在DOCTYPE中指定的那个文件,它规定了可以在xml出现什么标签、以及标签可以出现在哪等) 

START_DOCUMENT 
xml刚开始时,报告该事件 

END_DOCUMENT 
xml结束时,就报告该事件 

START_TAG 
读到开始标签时,就报告该事件。如:读到
这种时 

END_TAG 
读到结束标签时,就报告该事件。如:读到
这种时 


TEXT 
读到内容时,就报告该事件。如:读到
内容
,标签间的内容时 


xml的解析过程就是不断的请求事件,然后根据相应的事件做相应的处理  
XmlPullParser中提供的获取事件的方法: 
next(); 
主要是用于返回比较高层的事件的。其中包括:START_TAG, TEXT, END_TAG, END_DOCUMENT 

nextToken(); 
能够返回所有的事件。 

对于一般的解析,只需要用到XmlPullParser的几个获取值的api就够了: 
getName(); 
该api只有在当前的事件为START_TAG(返回标签名),END_TAG(返回标签名)和ENTITY_REF(返回实体引用名)。其它的事件都返回null。 

getText(); 
该api只有在当前的事件为TEXT(返回文本内容),ENTITY_REF(返回实体引用引用的内容),CDSECT(返回其内部的内容),COMMENT(返回注释内容)。其它的事件一般都返回null。 

nextText(); 
该api的正常执行是由条件的:要当前的事件为START_TAG,接下来两个事件为(TEXT), END_TAG。如果不满足就会抛异常(即:TEXT后再出现TEXT也是不行的)。如果当前事件为START_TAG,下一个为TEXT,则返回文本内容;如果下一个是END_TAG,则返回"",同时将事件置为END_TAG。 

一般用途的解析  
一般像微博这种,用xml作为数据交换时。返回的xml格式是很紧凑的(便于解析): 
849000ok0 
Xml代码   收藏代码
  1.   
  2. <root>  
  3.     <data>  
  4.         <create>8create>  
  5.         <fans>4fans>  
  6.         <home>9home>  
  7.         <mentions>0mentions>  
  8.         <private>0private>  
  9.     data>  
  10.     <errcode>0errcode>  
  11.     <msg>okmsg>  
  12.     <ret>0ret>  
  13. root>  

Java代码   收藏代码
  1. XmlPullParserFactory parserFactory = XmlPullParserFactory.newInstance();  
  2. XmlPullParser parser = parserFactory.newPullParser();  
  3. // 因为xml仅仅是数据,没有xml声明,doctype这种,所以不需要做任何设置,直接解析即可  
  4. FileReader reader = new FileReader(xmlFile);  
  5. parser.setInput(reader);  
  6.   
  7. // 该解析器是拉式解析器,所以只有靠我们自己去获取事件  
  8. // 当遇到END_DOCUMENT事件时,就可以结束事件的获取了,所以:  
  9. int eventType = 0;  
  10. String tagName = null;  
  11. while ((eventType = parser.next()) != XmlPullParser.END_DOCUMENT) {  
  12.     if (eventType == XmlPullParser.START_TAG) {  
  13.         tagName = parser.getName();  
  14.           
  15.         // 正常情况下,已知的标签是START_TAG + TEXT + END_TAG的。  
  16.         // 意外情况(比如服务器返回的xml不完整),此时就应该抛异常,所以这里就按照正常的逻辑写代码好了  
  17.         if ("create".equals(tagName)) {  
  18.             // setCreateNum(parser.nextText());  
  19.         } else if ("fans".equals(tagName)) {  
  20.             // setFansNum(parser.nextText());  
  21.         } else if ("home".equals(tagName)) {  
  22.             // setHomeNum(parser.nextText());  
  23.         } else if ("mentions".equals(tagName)) {  
  24.             // setMentions(parser.nextText());  
  25.         } else if ("private".equals(tagName)) {  
  26.             // setPrivateNum(parser.nextText());  
  27.         } else {  
  28.             // unknown or new tag, just pass it  
  29.         }  
  30.     }  
  31. }  


XmlPullParser其它api的使用  
// property, feature相关方法 
setFeature(String featureName, boolean state); 
setProperty(String propertName, Object value); 
getFeature(String featureName); 
getProperty(String propertyName); 

// xml读取方法 
setInput(Reader in); 
setInput(InputStream inputStream, String inputEncoding); 

// 事件请求方法 
next(); 
nextToken(); 
nextTag(); 
nextText(); 

// 其它相关方法 
require(int eventType, String namespace, String name); 
确定eventType是否和getEventType()相同,namespace是否和getNamespace()相同,name是否和getName()相同,有一个不同就抛异常。后两个可以为null(即忽略)。 

getInputEncoding(); 
获取输入xml的encoding。如果能确定则返回编码,否则返回null。 

// 事件类型都已int返回,要知道以文本方式显示的话可以这样 
int eventType = parser.getEventType(); 
String evtTypeText = XmlPullParser.TYPES[eventType]; 

// 其它方法见示例: 
要读取的xml文件: 
Xml代码   收藏代码
  1. xml version="1.0" encoding="UTF-8"?>  
  2. <persons  
  3.     xmlns:yd="http://www.china-mobile.com"  
  4.     xmlns:lt="http://www.china-unicome.com">  
  5.     some_content  
  6.     <person index="1">  
  7.         <name>yuanzhifei89name><age>100age><married>falsemarried>  
  8.         <yd:phone yd:id="amj08102">12345678yd:phone>  
  9.         <lt:phone lt:id="cmk35203">87654321lt:phone>  
  10.           
  11.         ]]><  
  12.     person>  
  13. persons>  

解析代码:从文档开始,一个事件一个事件解析到文档结束,基本涉及了所有api了。 
因为有些api只有在特定的事件上才有返回值,所以有些调用只在部分标签处使用。 
Java代码   收藏代码
  1. // 创建xml解析器  
  2. XmlPullParser parser = mFactory.newPullParser();  
  3. parser.setInput(new FileReader(xmlFile));  
  4.   
  5. // 因为使用的xml涉及了命名空间,所以启用命名空间  
  6. parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);  
  7.   
  8. int eventType = 0;  
  9.   
  10. // xml和person间的IGNOREABLE_WHITESPACE  
  11. eventType = parser.nextToken();  
  12. parser.isWhitespace(); // IGNOREABLE_WHITESPACE总是为whitespace  
  13.   
  14. // 返回这两个前缀对应的命名空间uri,但此时还未解析到命名空间部分,所以均返回null  
  15. parser.getNamespace("lt");  
  16. parser.getNamespace("yd");  
  17.   
  18. // 起始标签  
  19. eventType = parser.nextToken();  
  20. parser.getAttributeCount(); // 0,persones标签没有属性  
  21.   
  22. // 命名空间已解析  
  23. parser.getNamespace("lt"); // http://www.china-unicome.com  
  24. parser.getNamespace("yd"); // http://www.china-mobile.comp  
  25.   
  26. // 间的text(空白也算在text内容中)  
  27. eventType = parser.nextToken();  
  28. parser.isWhitespace(); // false,只要含有非空白字符就不是whitespace  
  29.   
  30. // 起始标签  
  31. eventType = parser.nextToken();  
  32.   
  33. // 间的text  
  34. eventType = parser.nextToken();  
  35. parser.isWhitespace(); // true  
  36.   
  37. // 起始标签  
  38. eventType = parser.nextToken();  
  39. parser.getLineNumber(); // 第7行  
  40. parser.getColumnNumber(); // 第9列  
  41.   
  42. // name标签中的text:yuanzhifei89  
  43. eventType = parser.nextToken();  
  44.   
  45. // 结束标签  
  46. eventType = parser.nextToken();  
  47.   
  48. // 起始标签  
  49. eventType = parser.nextToken();  
  50. parser.getNamespace(); // "",age没有命名空间  
  51. parser.isEmptyElementTag(); // false,age并不是这种空标签  
  52. parser.getDepth(); // 3,一层,二层,到它就是三层  
  53. parser.getNamespaceCount(parser.getDepth()); // 2,到三层为止解析到了2个命名空间  
  54. // age标签中的text:100  
  55. eventType = parser.nextToken();  
  56. // 结束标签  
  57. eventType = parser.nextToken();  
  58.   
  59. // 开始标签  
  60. eventType = parser.nextToken();  
  61. // 标签married间的text:false  
  62. eventType = parser.nextToken();  
  63. // 结束标签  
  64. eventType = parser.nextToken();  
  65.   
  66. // 和

你可能感兴趣的:(android xml解析XmlPullParser的使用)