DOM、SAX、PULL方式解析XML

DOM、SAX、PULL方式解析XML

实际编程中,我们经常需要用到XML文档,它能实现实体类对象的序列化保存,我们也很容易将XML文件内容反解成为实体类对象集合。下面的内容将介绍如何以DOM、SAX、PULL三种方式实现XML文件的解析。

我们以示例的方式方便讲解。

首先设定一个XML文件内容为,并将其保存到Android项目的assets文件夹中:

1.  <?xml version="1.0" encoding="utf-8"?>  

2.  <persons>  

3.      <person>  

4.          <id>001</id>  

5.          <name>张三</name>  

6.          <sex></sex>  

7.      </person>  

8.      <person>  

9.          <id>002</id>  

10.         <name>李四</name>  

11.         <sex></sex>  

12.     </person>  

13.     <person>  

14.         <id>003</id>  

15.         <name>王二麻子</name>  

16.         <sex></sex>  

17.     </person>  

18. </persons>  

那么对应的实体类PersonBean.java的内容就是:

1.  package com.example.bigbigboy.bean;

2.  /**

3.   *Created by BigBigBoy on 2015/3/11.

4.   */

5.  public class PersonBean {

6.      private int id;

7.      private String name;

8.      private String sex;

9.      public int getId() {

10.         return id;}

11.     public void setId(int id) {

12.         this.id = id;}

13.     public String getName() {

14.         return name;}

15.     public void setName(String name) {

16.         this.name = name;}

17.     public String getSex() {

18.         return sex;}

19.     public void setSex(String sex) {

20.         this.sex = sex;}

21.     @Override

22.     public String toString() {

23.         return "id--->" + id +"\nname--->" + name + "\nsex--->" + sex;}}

     由于涉及到多种方式解析和序列化XML文件,但是我们主要面对两个方法,为了分离方法的调用和具体是实现的,我们这里定义一个接口XmlOperate,它包括解析和序列化两个方法:

1.  package com.example.xml;

2.  import com.example.bigbigboy.bean.PersonBean;

3.  import java.io.InputStream;

4.  import java.util.List;

5.   

6.  /**

7.   *Created by BigBigBoy on 2015/3/11.

8.   */

9.  public interface  XmlOperate {

10.     /**

11.      *解析输入流得到PersonBean对象集合

12.      *@param is

13.      *@return

14.      *@throws Exception

15.      */

16.     public List<PersonBean>xmlParse(InputStream is) throws Exception;

17.     /**

18.      *序列化PersonBean对象集合得到XML形式的字符串

19.      *@param persons

20.      *@return

21.      *@throws Exception

22.      */

23.     public StringxmlSerialize(List<PersonBean> persons) throws Exception;

24. }

为了直观的观察解析后的结果,我们创建一个MainActivity.class,并在界面中放置一个ListView来展示解析的结果,两个按钮,分别实现解析和序列化两个功能。界面布局如下:


   其中解析按钮下的代码为:

1.  public void onParseClick(View view) throwsException {

2.          //XmlOperate xmlOperate = newSAX_Person();

3.          //XmlOperate xmlOperate = newDOM_Person();

4.          XmlOperate xmlOperate = newPULL_Person();

5.          List<PersonBean> list =xmlOperate.xmlParse(getResources().getAssets().open("persons.xml"));

6.          listViewAdapter = newListViewAdapter(this, list);

7.          listView.setAdapter(listViewAdapter);

8.      }

       序列化下的按钮代码为:

1.  public void onSaveClick(View view) throwsException {

2.          XmlOperate xmlOperate = newSAX_Person();

3.          //XmlOperate xmlOperate = newDOM_Person();

4.          //XmlOperate xmlOperate = newPULL_Person();

5.          List<PersonBean> list =xmlOperate.xmlParse(getResources().getAssets().open("persons.xml"));

6.         Log.d("xmlSerialize",xmlOperate.xmlSerialize(list));

7.      }

就这样,在我们还完全没有实现真正的代码解析和序列化功能的情况下,我们却已经完成了前面的使用部分代码,接下来我们只需要分别去实现DOM、SAX、PULL三种方式的解析和序列化功能就行了。

使用DOM解析器下的代码:

1.  package com.example.xml.DOMOperate;

2.  /**

3.   *Created by BigBigBoy on 2015/3/11.

4.   */

5.  public class DOM_Person implements XmlOperate{

6.      @Override

7.      public List<PersonBean>xmlParse(InputStream is) throws Exception {

8.          List<PersonBean> persons = newArrayList<PersonBean>();

9.          DocumentBuilderFactory factory =DocumentBuilderFactory.newInstance();  //取得DocumentBuilderFactory实例 

10.         DocumentBuilder builder =factory.newDocumentBuilder(); //factory获取DocumentBuilder实例 

11.         Document doc = builder.parse(is);   //解析输入流得到Document实例 

12.         Element rootElement =doc.getDocumentElement();

13.         NodeList items =rootElement.getElementsByTagName("person");

14.         for (int i = 0; i <items.getLength(); i++) {

15.             PersonBean person = newPersonBean();

16.             Node item = items.item(i);

17.             NodeList properties =item.getChildNodes();

18.             for (int j = 0; j <properties.getLength(); j++) {

19.                 Node property = properties.item(j);

20.                 String nodeName =property.getNodeName();

21.                 if(nodeName.equals("id")) {

22.                     person.setId(Integer.parseInt(property.getFirstChild().getNodeValue()));

23.                 } else if(nodeName.equals("name")) {

24.                     person.setName(property.getFirstChild().getNodeValue());

25.                 } else if(nodeName.equals("sex")) {

26.                     person.setSex(property.getFirstChild().getNodeValue());

27.                 }

28.             }

29.             persons.add(person);

30.         }

31.         return persons;

32.     }

33.  

34.     @Override

35.     public StringxmlSerialize(List<PersonBean> persons) throws Exception {

36.         DocumentBuilderFactory factory =DocumentBuilderFactory.newInstance();

37.         DocumentBuilder builder =factory.newDocumentBuilder();

38.         Document doc =builder.newDocument();   //builder创建新文档 

39.         Element rootElement =doc.createElement("persons");

40.         for (PersonBean person : persons) {

41.             Element personElement =doc.createElement("person");

42.             personElement.setAttribute("id",person.getId() + "");

43.             Element nameElement =doc.createElement("name");

44.             nameElement.setTextContent(person.getName());

45.             personElement.appendChild(nameElement);

46.             Element priceElement =doc.createElement("sex");

47.             priceElement.setTextContent(person.getSex()+ "");

48.             personElement.appendChild(priceElement);

49.             rootElement.appendChild(personElement);

50.         }

51.         doc.appendChild(rootElement);

52.         TransformerFactory transFactory =TransformerFactory.newInstance();//取得TransformerFactory实例

53.         Transformer transformer =transFactory.newTransformer();    //transFactory获取Transformer实例

54.         transformer.setOutputProperty(OutputKeys.ENCODING,"UTF-8");            //设置输出采用的编码方式

55.         transformer.setOutputProperty(OutputKeys.INDENT,"yes");                //是否自动添加额外的空白          transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION,"no");   //是否忽略XML声明 

56.         StringWriter writer = newStringWriter();

57.         Source source = new DOMSource(doc); //表明文档来源是doc

58.         Result result = newStreamResult(writer);//表明目标结果为writer

59.         transformer.transform(source,result);  //开始转换 

60.         return writer.toString();   

61. }}

       使用SAX解析器下的代码:(由于SAX解析器的事件+处理者分离模型,我们将它分为SAX_Person和SAXPersonHandler两个类)

1.  package com.example.xml.SAXOperate;

2.  /**

3.   *Created by BigBigBoy on 2015/3/11.

4.   */

5.  public class SAX_Person implements XmlOperate{

6.      @Override

7.      public List<PersonBean>xmlParse(InputStream is) throws Exception {

8.          SAXParserFactory factory =SAXParserFactory.newInstance();  //取得SAXParserFactory实例

9.          SAXParser parser = factory.newSAXParser();                  //factory获取SAXParser实例

10.         SAXPersonHandler handler = newSAXPersonHandler();            //实例化自定义Handler

11.         parser.parse(is, handler);                                  //根据自定义Handler规则解析输入流

12.         return handler.getPersons();

13.     }

14.  

15.     @Override

16.     public StringxmlSerialize(List<PersonBean> persons) throws Exception {

17.         SAXTransformerFactory factory =(SAXTransformerFactory) TransformerFactory.newInstance();//取得SAXTransformerFactory实例 

18.         TransformerHandler handler =factory.newTransformerHandler();          //factory获取TransformerHandler实例 

19.         Transformer transformer =handler.getTransformer();                    //handler获取Transformer实例 

20.         transformer.setOutputProperty(OutputKeys.ENCODING,"UTF-8");            //设置输出采用的编码方式 

21.         transformer.setOutputProperty(OutputKeys.INDENT,"yes");                //是否自动添加额外的空白 

22.         transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION,"no");   //是否忽略XML声明 

23.  

24.         StringWriter writer = newStringWriter();

25.         Result result = newStreamResult(writer);

26.         handler.setResult(result);

27.  

28.         String uri = "";    //代表命名空间的URIURI无值时须置为空字符串 

29.         String localName = "";  //命名空间的本地名称(不包含前缀)当没有进行命名空间处理时须置为空字符串 

30.  

31.         handler.startDocument();

32.         handler.startElement(uri, localName,"persons", null);

33.  

34.         AttributesImpl attrs = newAttributesImpl();    //负责存放元素的属性信息 

35.         char[] ch = null;

36.         for (PersonBean person : persons) {

37.             attrs.clear();  //清空属性列表 

38.             attrs.addAttribute(uri, localName,"id", "string", String.valueOf(person.getId()));//添加一个名为id的属性(type影响不大,这里设为string) 

39.             handler.startElement(uri,localName, "person", attrs);   //开始一个person元素关联上面设定的id属性 

40.  

41.             handler.startElement(uri, localName,"name", null); //开始一个name元素没有属性 

42.             ch =String.valueOf(person.getName()).toCharArray();

43.             handler.characters(ch, 0,ch.length);   //设置name元素的文本节点 

44.             handler.endElement(uri, localName,"name");

45.  

46.             handler.startElement(uri,localName, "sex", null);//开始一个sex元素没有属性 

47.             ch =String.valueOf(person.getSex()).toCharArray();

48.             handler.characters(ch, 0,ch.length);   //设置sex元素的文本节点 

49.             handler.endElement(uri, localName,"sex");

50.  

51.             handler.endElement(uri, localName,"person");

52.         }

53.         handler.endElement(uri, localName,"persons");

54.         handler.endDocument();

55.         return writer.toString();

56.     }

57. }

SAXPersonHandler类代码:

1.    package com.example.xml.SAXOperate;

2.   

3.  /**

4.   *Created by BigBigBoy on 2015/3/11.

5.   */

6.  public class SAXPersonHandler extendsDefaultHandler {

7.   

8.      private List<PersonBean> persons;

9.      private PersonBean person;

10.     private StringBuilder builder;

11.  

12.     //返回解析后得到的Person对象集合 

13.     public List<PersonBean> getPersons(){

14.         return persons;

15.     }

16.  

17.     @Override

18.     public void startDocument() throwsSAXException {

19.         super.startDocument();

20.         persons = newArrayList<PersonBean>();

21.         builder = new StringBuilder();

22.     }

23.  

24.     @Override

25.     public void startElement(String uri, StringlocalName, String qName, Attributes attributes) throws SAXException {

26.         super.startElement(uri, localName,qName, attributes);

27.         if(localName.equals("person")) {

28.             person = new PersonBean();

29.         }

30.         builder.setLength(0);   //将字符长度设置为0以便重新开始读取元素内的字符节点 

31.     }

32.  

33.     @Override

34.     public void characters(char[] ch, intstart, int length) throws SAXException {

35.         super.characters(ch, start, length);

36.         builder.append(ch, start, length);  //将读取的字符数组追加到builder 

37.     }

38.  

39.     @Override

40.     public void endElement(String uri, StringlocalName, String qName) throws SAXException {

41.         super.endElement(uri, localName,qName);

42.         if (localName.equals("id")) {

43.             person.setId(Integer.parseInt(builder.toString()));

44.         } else if(localName.equals("name")) {

45.             person.setName(builder.toString());

46.         } else if(localName.equals("sex")) {

47.             person.setSex(builder.toString());

48.         } else if(localName.equals("person")) {

49.             persons.add(person);

50.         }

51.     }

52. }

使用PULL解析器的代码:

1.  package com.scott.xml.parser;    

2.  public class PullBookParser implementsBookParser {        

3.      @Override 

4.      public List<Book> parse(InputStreamis) throws Exception { 

5.          List<Book> books = null; 

6.          Book book = null;            

7.  //     XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); 

8.  //     XmlPullParser parser = factory.newPullParser();            

9.          XmlPullParser parser =Xml.newPullParser(); //android.util.Xml创建一个XmlPullParser实例 

10.         parser.setInput(is,"UTF-8");               //设置输入流并指明编码方式    

11.         int eventType =parser.getEventType(); 

12.         while (eventType !=XmlPullParser.END_DOCUMENT) { 

13.             switch (eventType) { 

14.             caseXmlPullParser.START_DOCUMENT: 

15.                 books = newArrayList<Book>(); 

16.                 break; 

17.             case XmlPullParser.START_TAG: 

18.                 if(parser.getName().equals("book")) { 

19.                     book = new Book(); 

20.                 } else if (parser.getName().equals("id")){ 

21.                     eventType =parser.next(); 

22.                     book.setId(Integer.parseInt(parser.getText())); 

23.                 } else if(parser.getName().equals("name")) { 

24.                     eventType =parser.next(); 

25.                     book.setName(parser.getText()); 

26.                 } else if(parser.getName().equals("price")) { 

27.                     eventType =parser.next(); 

28.                     book.setPrice(Float.parseFloat(parser.getText())); 

29.                 } 

30.                 break; 

31.             case XmlPullParser.END_TAG: 

32.                 if(parser.getName().equals("book")) { 

33.                     books.add(book); 

34.                     book = null; } 

35.                 break;  } 

36.             eventType = parser.next();} 

37.         return books;  }        

38.     @Override 

39.     public String serialize(List<Book>books) throws Exception { 

40. //     XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); 

41. //     XmlSerializer serializer = factory.newSerializer();            

42.         XmlSerializer serializer =Xml.newSerializer(); //android.util.Xml创建一个XmlSerializer实例 

43.         StringWriter writer = newStringWriter(); 

44.         serializer.setOutput(writer);   //设置输出方向为writer 

45.         serializer.startDocument("UTF-8",true); 

46.         serializer.startTag("","books"); 

47.         for (Book book : books) { 

48.             serializer.startTag("","book"); 

49.             serializer.attribute("","id", book.getId() + "");               

50.             serializer.startTag("","name"); 

51.             serializer.text(book.getName()); 

52.             serializer.endTag("","name");                

53.             serializer.startTag("","price"); 

54.             serializer.text(book.getPrice() +""); 

55.             serializer.endTag("","price");                

56.             serializer.endTag("","book");} 

57.         serializer.endTag("","books"); 

58.         serializer.endDocument();            

59.         return writer.toString(); 

60.  }  } 

   上面的代码完全实现了DOM、SAX、PULL三种方式对XML文件的解析以及实体类对象序列化为XML文件。虽然它们都能实现这样的功能,但是在性能以及代码量方面却有所不同。

DOM(Document Object Model,简称DOM,中文:文档对象模型):使用DOM方式解析XML时,我们需要读入整个的XML文档,然后在内存中创建DOM树,生成DOM树上的每个Node对象,即所有的文档内容将一次性全部被解析到内存中,因此它对内存消耗是比较大的,尤其在文档比较大的时候。但是它也具有其他方式所不具有的优势,因为在内存中。他的检索和更新效率特别高,可以随机访问任意元素或在任意位置插值,而SAX和PULL方式都不能实现。

SAX(Simple API for XML)模型:相对于DOM方式,SAX方式并不会将整个文档加载到内存,而是从文档的开始往下依次读取,基于事件模型,当某个事件被触发时,才获取相应的XML的部分数据,从而不管XML文件有多大,都只占用了少量的内存空间。但是,SAX是从文档开始执行遍历的。并且只能遍历一次。也就是说我们不能随机的访问XML文件,只能从头到尾的将XML文件遍历一次(当然也可以中间截断遍历)。

PULL方式:它和SAX方式极为相似,都是基于事件模型。PULL解析器小巧轻便,解析速度快,简单易用,非常适合在Android移动设备中使用,Android系统内部在解析各种XML时也是用PULL解析器。

 

 

以上内容几乎全部参考与博客:http://blog.csdn.net/liuhe688/article/details/6415593

自己真正操作一遍加深了印象,以前看过多次,一直都记不住,这次记得脑一些了。

 

上面是你合计的代码全部都可以在Github仓库中下载:

https://github.com/BBigBoy/AndroidBaseTest   XMLParser项目。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值