加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

三种XML解析方法总结

发布时间:2020-12-16 09:22:26 所属栏目:百科 来源:网络整理
导读:SAX解析 如果要用SAX来解析xml文档,则需要一个类来继承android系统提供的ContentHandler类。但是如果继承ContentHandler这个类,即使你不使用这个类提供的所有方法,你也必须实现其内部的所有方法(一般情况下没有使用的方法可以直接用空方法代替),但是这样

SAX解析

如果要用SAX来解析xml文档,则需要一个类来继承android系统提供的ContentHandler类。但是如果继承ContentHandler这个类,即使你不使用这个类提供的所有方法,你也必须实现其内部的所有方法(一般情况下没有使用的方法可以直接用空方法代替),但是这样开发起来不是很方便。因此我们可以改为继承DefaultHandler这个类,这样的话我们只需要实现程序中所需要的方法即可,其它的方法这个类内部其实已经用空方法代替了。

[java] view plain copy
  1. ContentHandler接口的方法有以下几种:
  2. voidstartDocument();//文档解析开始时执行
  3. voidendDocument();//文档解析结束时执行
  4. voidstartElement(Stringuri,StringlocalName,StringqName,Attributesatts);//标签开始解析时执行
  5. voidendElement(Stringuri,0); background-color:inherit">//标签解析结束时执行
  6. voidcharacters(char[]ch,intstart,153); font-weight:bold; background-color:inherit">intlength);//解析标签属性时执行

android中使用SAX来解析xml文件,需先建立一个SAX工厂,即SAXParserFactory对象,还需建立一个XMLReader对象,该类绑定ContentHandler子类,且与xml源文件结合在一起。即其处理过程为创建事件处理程序,创建SAX解析器,键事件处理程序分配给解析器,对文档进行解析,将每个事件发送给处理程序。

1.在src目录下新建一个android.xml文件

[html]
    <?xmlversion="1.0"encoding="UTF-8"?>
  1. <persons>
  2. personid="23">
  3. name>xiaanming</age>23personpersonid="20">liudehua>28>

2.新建一个Person.class用来存放解析的对象

    packagecom.example.xml_parser;
  1. publicclassPerson{
  2. privateintid;
  3. privateStringname;
  4. intage;
  5. publicPerson(){}
  6. publicPerson(intid,Stringname,153); font-weight:bold; background-color:inherit">intage){
  7. this.id=id;
  8. this.name=name;
  9. this.age=age;
  10. }
  11. intgetId(){
  12. returnid;
  13. voidsetId(intid){
  14. publicStringgetName(){
  15. returnname;
  16. voidsetName(Stringname){
  17. this.name=name;
  18. intgetAge(){
  19. returnage;
  20. voidsetAge( @Override
  21. publicStringtoString(){
  22. return"id="+id+",name"+name+",age="+age;
  23. }
  24. }

3.新建一个SAXforHandler类继承DefaultHandler,而DefaultHandler实现了ContentHandler接口,需要重写我们需要的方法

    importjava.io.BufferedReader;
  1. importjava.io.IOException;
  2. importjava.io.InputStream;
  3. importjava.io.InputStreamReader;
  4. importjava.util.ArrayList;
  5. importjava.util.List;
  6. importjavax.xml.parsers.SAXParser;
  7. importjavax.xml.parsers.SAXParserFactory;
  8. importorg.xml.sax.Attributes;
  9. importorg.xml.sax.InputSource;
  10. importorg.xml.sax.SAXException;
  11. importorg.xml.sax.XMLReader;
  12. importorg.xml.sax.helpers.DefaultHandler;
  13. importandroid.util.Log;
  14. classSAXforHandlerextendsDefaultHandler{
  15. staticfinalStringTAG="SAXforHandler";
  16. /**
  17. *用来存放解析的Person对象
  18. */
  19. privateList<Person>persons;
  20. /**
  21. *Person对象的引用,记录当前的Person
  22. */
  23. privatePersonperson;
  24. *通过此变量,记录当前一个标签的名称
  25. privateStringtag;
  26. *此方法只有在开始解析文档的时候执行一次,比较适合处理一些初始化的东西
  27. *我new了一个ArrayList<Person>()对象和打印Log
  28. @Override
  29. voidstartDocument()throwsSAXException{
  30. persons=newArrayList<Person>();
  31. Log.i(TAG,"****startDocument*****");
  32. *文档解析完了调用的回调方法
  33. voidendDocument()throwsSAXException{
  34. "****endDocument*****");
  35. *uri是命名空间
  36. *localName标签的名称,如name,age等
  37. *qName带命名空间的标签名
  38. *Attributes存放改标签的所有属性
  39. *
  40. *当localName为person的时候,我们拿出person标签的属性值,此处由于只有一个属性,也可以直接person.setId(Integer.valueOf(attributes.getValue(0)));
  41. *然后设置tag=person,这个方法执行完了,然后会执行回调方法characters(char[]ch,intstart,intlength),这是一个循环的过程
  42. if("person".equals(localName)){
  43. for(inti=0;i<attributes.getLength();i++){
  44. "attributesName:"+attributes.getLocalName(i)+"__attributesValue:"+attributes.getValue(i));
  45. person=newPerson();
  46. person.setId(Integer.valueOf(attributes.getValue(i)));
  47. tag=localName;
  48. Log.i(TAG,"localName="+localName);
  49. *这个方法只要是获取两个标签里面的值的,这里最好用trim()方法过滤下,可以避免读取到的XML有空格带来不必要的麻烦
  50. *执行完这个方法就执行回调方法endElement(Stringuri,StringqName),这也是一个循环的过程
  51. intlength)
  52. Stringdate=newString(ch,start,length).trim();
  53. if(!"".equals(date)){
  54. "Content:"+date);
  55. if("name".equals(tag)){
  56. person.setName(date);
  57. }elseif("age".equals(tag)){
  58. person.setAge(Integer.valueOf(date));
  59. *uri,localName,qName跟上面的一个意思
  60. *当localName=person并且person对象为null时,说明一个person对象解析完毕
  61. *将person加入到List当中
  62. *每个标签解析完了需要将tag=null
  63. if("person".equals(localName)&&person!=null){
  64. persons.add(person);
  65. null;
  66. tag=null;
  67. *拿到成员变量List<Person>persons的方法
  68. *@return
  69. publicList<Person>getPersons(){
  70. returnpersons;
  71. *1.加载需要解析的文件,因为XML放在src目录下,可以通过类装载器的方法获得文件路径,在以输入流的方式加入解析器
  72. *2.解析XML有两种形式,创建一个XMLReader或者直接使用XMLParser
  73. *@throwsException
  74. staticList<Person>sax_XML()throwsException{
  75. InputStreamis=MainActivity.class.getClassLoader().getResourceAsStream("android.xml");
  76. <spanstyle="font-size:32px;color:#ff0000;">/**坑爹的地方,当我调用getInputStreamContent(InputStreamis)这个方法时,解析就错误,不知道为什么???*/
  77. </span>
  78. SAXforHandlersaXforHandler=newSAXforHandler();
  79. SAXParserFactoryspf=SAXParserFactory.newInstance();
  80. SAXParsersaxParser=spf.newSAXParser();
  81. //使用XMLReader的方式
  82. //XMLReaderxmlReader=saxParser.getXMLReader();
  83. //xmlReader.setContentHandler(saXforHandler);
  84. //xmlReader.parse(newInputSource(is));
  85. //直接使用XMLParser,推荐使用这种
  86. saxParser.parse(is,saXforHandler);
  87. //获取解析好了的List对象
  88. List<Person>list=saXforHandler.getPersons();
  89. is.close();
  90. returnlist;
  91. *测试方法,根据输入流获取里面的内容
  92. *@paramis
  93. *@throwsIOException
  94. staticStringgetInputStreamContent(InputStreamis)throwsIOException{
  95. StringBuffersb=newStringBuffer();
  96. BufferedReaderbr=newBufferedReader(newInputStreamReader(is));
  97. Stringline;
  98. while((line=br.readLine())!=null){
  99. sb.append(line);
  100. br.close();
  101. returnsb.toString();
  102. }


DOM解析
DOM比SAX更容易掌握,因为她没有涉及回调和复杂的状态管理,然而,DOM的实现常常将所有的XML节点保存在内存中,这样使的处理较大的文档效率低。

XML基本的节点类型

node - DOM基本的数据类型

Element - 最主要处理的对象是Element

Attr - 元素的属性

Text - 一个Element 或者Attr的实际内容

Document - 代表整个XML文档,一个Document对象通常也称为一颗DOM树

1 新建一个DomPersonService.class,注释我写的清楚,大家自己看

[java] view plain copy
    packagecom.example.dom_parser;
  1. importjava.util.ArrayList;
  2. importjava.util.List;
  3. importjavax.xml.parsers.DocumentBuilder;
  4. importjavax.xml.parsers.DocumentBuilderFactory;
  5. importorg.w3c.dom.Document;
  6. importorg.w3c.dom.Element;
  7. importorg.w3c.dom.Node;
  8. importorg.w3c.dom.NodeList;
  9. classDomPersonService{
  10. staticList<Person>readXML()throwsThrowable{
  11. //获得android.xml文件的输入流
  12. List<Person>persons=newArrayList<Person>();
  13. //实例化DocumentBuilderFactory和DocumentBuilder,并创建Document
  14. DocumentBuilderFactoryfactory=DocumentBuilderFactory.newInstance();
  15. DocumentBuilderbuilder=factory.newDocumentBuilder();
  16. Documentdocument=builder.parse(is);
  17. //返回文档的根(root)元素
  18. ElementrootElement=document.getDocumentElement();
  19. //获取一个Note(DOM基本的数据类型)集合,这里有两个personNote
  20. NodeListnodes=rootElement.getElementsByTagName("person");
  21. //遍历Note集合
  22. 0;i<nodes.getLength();i++){
  23. //先从第一个person元素开始解析
  24. ElementpersonElement=(Element)nodes.item(i);
  25. Personperson= person.setId(Integer.valueOf(personElement.getAttribute("id")));
  26. //获取person下面的name和age的Note集合
  27. NodeListchileNodes=personElement.getChildNodes();
  28. inty=0;y<chileNodes.getLength();y++){
  29. NodechildNode=chileNodes.item(y);
  30. //判断子Note的类型为元素Note
  31. if(childNode.getNodeType()==Node.ELEMENT_NODE){
  32. ElementchildElement=(Element)childNode;
  33. if("name".equals(childElement.getNodeName())){
  34. person.setName(childElement.getFirstChild().getNodeValue());
  35. if("age".equals(childElement.getNodeName())){
  36. person.setAge(Integer.valueOf(childElement.getFirstChild().getNodeValue()));
  37. Log.e("log",person.toString());
  38. returnpersons;
  39. }

关于DOM解析XML,我们要清楚的知道个节点之间的关系,才能更好的操作对象树,值得注意的是在建立Element时,要注意jar包的导入, 要选择org.w3c.dom.Element,而不是其他的包.


Pull解析

1.Pull简介

Pull解析器是Android系统内置的的,Pull解析器与SAX解析器类似,他提供了类似的事件,如开始元素和介绍元素的事件,使用parser.next()可以进入下一个元素并触发相应的事件,然后进行相应的处理,当元素开始解析时,调用perser.nextText()方法就可以获取到下一个Text类型元素的值。

2.pull特点

一.简单的结构,一个接口,一个另外,一个工厂组成了Pull解析器

二.简单易用,Pull解析器只有一个重要的方法next(),他被用来检索下一个事件,而他的事件也仅仅只有五个,START_DOCUMENT,START_TAG,TEXT,END_TAG,END_DOCUMENT

三.最小的内存消耗,Pull解析器和SAX解析器一样,对内存的暂用少,但是SAX解析稍微有点繁琐,DOM很耗内存,所以Pull被推荐使用

3,示例 Pull解析XML

新建一个PullXMLService

[java] view plain copy
    packagecom.example.pull_parser;
  1. importorg.xmlpull.v1.XmlPullParser;
  2. importandroid.util.Xml;
  3. classPullXMLService{
  4. throwsException{
  5. //获取src目录下面的android.xml文件的输入流
  6. InputStreamis=PullXMLService.//用来存放解析的Person对象
  7. List<Person>persons=//一个标记
  8. booleanflag=false;
  9. Personperson=//实例化一个XmlPullParser对象
  10. XmlPullParserparser=Xml.newPullParser();
  11. //设置输入流和编码
  12. parser.setInput(is,"UTF-8");
  13. //触发了第一个事件,根据XML的语法,也就是从他开始了解文档
  14. inteventCode=parser.getEventType();
  15. //如果获得的事件码如果是文档的结束,那么解析结束
  16. while(eventCode!=XmlPullParser.END_DOCUMENT){
  17. switch(eventCode){
  18. caseXmlPullParser.START_DOCUMENT:{
  19. //开始解析的时候我们一般做一些初始化的操作
  20. persons=break;
  21. caseXmlPullParser.START_TAG:{
  22. //判断当前的元素是否是需要检索的元素
  23. if("person".equals(parser.getName())){
  24. flag=true;
  25. person.setId(Integer.valueOf(parser.getAttributeValue(0)));
  26. if(flag){
  27. if("name".equals(parser.getName())){
  28. person.setName(parser.nextText());
  29. }if("age".equals(parser.getName())){
  30. person.setAge(Integer.valueOf(parser.nextText()));
  31. caseXmlPullParser.END_TAG:{
  32. if("person".equals(parser.getName())&&person!= flag= Log.e("log",person.toString());
  33. person=break;
  34. //这一步很重要,该方法返回一个事件码,也是触发下一个事件的方法
  35. eventCode=parser.next();
  36. }

好了,这样子就解析完了android.xml 是不是很方便很简单呢,比SAX和DOM要更容易理解。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读