解析XML:DOM、SAX、PULL

来源:互联网 发布:淘宝手工护肤哪家好 编辑:程序博客网 时间:2024/04/30 05:39

这三种方法中DOM最耗内存,因为它是把整个文件加载进去然后进行分类整理的,PULL和SAX类似,只是SAX要用到一个解析类,类中的主要三个方法完成内容的解析。


》Sax定义

         SAX是一个解析速度快并且占用内存少的xml解析器,非常适合用于android等移动设备

         SAX全称是Simple API for Xml,既是指一种接口,也是一个软件包

         作为接口,sax是事件驱动型xml解析的一个标准接口,android的事件机制是基于回调函数

》Sax特点

        1. 解析效率高,占用内存少

        2.可以随时停止解析

        3.不能载入整个文档到内存

        4.不能写入xml

        5.SAX解析xml文件采用的是事件驱动

---sax并不需要解析完 整个文档,在按内容顺序解析文档的过程中,sax会判断当前读到的字符是否合法xml语法中的某部分,如果符合就会触发事件

》Sax工作原理

         Sax的工作原理简单的说,就是对文档进行顺序扫描,扫描到文档(document)开始与结束,扫描到元素(element)开始、结束等地方时调用事件处理

         处理函数做相应动作,然后继续扫描,直到文档结束。

》Sax解析文档过程

           1.继承DefaultHandler  ,并实现方法      

           2.创建SAX解析器工厂

           3.获得解析器

           4.获得输入流

           5.使用输入流,和实现接口作参数,调用解析器的解析方法进行解析


》defaultHandler 接口是实现contentHandler接口

         ContentHandler接口中的常用方法

                 >startDocument()

                            当遇到文档开头的时候,调用这个方法,可以在其中做一些与准备工作

                 >endDocument()

                             当文档结束的时候,调用这个方法,可以在其中做一些善后工作

                 >startElement(String namespaceURL, String localName, String qName, Attributes atts)

                             当读到一个开始标签的时候,会触发这个方法。namespaceURL就是命名空间,localName是不带命名空间前缀的标签名,

                             qName是待命名空间前缀的标签名。通过atts可以得到所有的属性名和相应的值。

                 >endElement(String uri, String localName, String name)

                            当遇到结束标签的时候,调用这个方法

                 >characters(char[] ch, int start, int length)

                            这个方法用来处理在xml文件中读到的内容,第一个参数为文件的字符串内容,后面两个参数是读到的字符串在这个数组中的起始位置和长度,

                            使用new String(ch, start, length)就可以获取内容


》DOM简介

        dom全称Document Object Model ,为xml文档的已解析版本定义了一组接口。解析器读入整个文档,然后构建一个主流内存的树结构,

         然后代码就可以使用dom接口来操作这个树结构

》DOM的特点

         >优点

                  1.整个文档树在内存中,便于操作;支持删除、修改、重新排列等多种功能

                  2.通过树形结构存取xml文档

                  3.可以在树的某个节点上向前或向后移动

           >缺点

                  1.将整个文档调入内存(包括无用的节点),浪费时间和空间

            >适用场合

                  一旦解析了文档还需多次访问这些数据;硬件资源充足(内存,cpu)

》DOM解析步骤

      1.创建解析器工厂

      2.获得解析器工厂

      3.接受一个xml文档作为输入参数名,并得到一个xml的文档对象(Document)

      4.操作文档对象


》pull解析器简介

        1.pull解析器是android内置的解析器,解析原理与sax类似

        2.pull它提供了类似的事件。

              如:开始元素和结束元素事件,使用parse.next()可以进入下一个元素并触发相应的事件,事件将作为数值代码被发送

                      因此可以使用一个switch对感兴趣的事件进行处理。当元素开始解析时,调用parser.nextText()方法获取下一个Text类型节点的值


》pull与sax的不同之处

          1.pull读取xml文件后触发相应的事件调用方法返回的是数字。

          2.pull可以在程序中控制,想解析到哪里就可以停止到哪里


》pull解析步骤

      1.创建解析器对象

          XmlPullParser paser = Xml.newPullParser();

      2.进行解析

             paser.setInput(input,"utf-8");

      3.产生第一个解析事件

              int eventType = paser.getEventType();

       4.可以使用循环判断是否继续解析

                while(eventType!=XmlPullParser.END_DOCUMENT){}



首先我们准备好我们要解析的资源文件和封装好的javaBean。

person.xml

[java] view plaincopy
  1. <?xml version="1.0" encoding="UTF-8"?>    
  2. <persons>  
  3.     <person id="1">  
  4.         <name>sax</name>  
  5.         <age>12</age>  
  6.     </person>  
  7.     <person id="2">  
  8.         <name>ganganrou</name>  
  9.         <age>17</age>  
  10.     </person>  
  11.     <person id="3">  
  12.         <name>nuanwozi</name>  
  13.         <age>5</age>  
  14.     </person>  
  15. </persons>  

封装好的javaBean

[java] view plaincopy
  1. public class PersonBean {  
  2.     int id;  
  3.     String name;  
  4.     String age;  
  5.   
  6.     public int getId() {  
  7.         return id;  
  8.     }  
  9.   
  10.     public void setId(int id) {  
  11.         this.id = id;  
  12.     }  
  13.   
  14.     public String getName() {  
  15.         return name;  
  16.     }  
  17.   
  18.     public void setName(String name) {  
  19.         this.name = name;  
  20.     }  
  21.   
  22.     public String getAge() {  
  23.         return age;  
  24.     }  
  25.   
  26.     public void setAge(String age) {  
  27.         this.age = age;  
  28.     }  
  29.   
  30.     @Override  
  31.     public String toString() {  
  32.         return "PersonBean [id=" + id + ", name=" + name + ", age=" + age + "]";  
  33.     }  
  34.   
  35. }  

接下来我们分别以DOM、SAX、PULL的方式对person.xml文件进行解析并封装到javaBean中去:

一、DOM

[java] view plaincopy
  1. public static List<PersonBean> getPersonBeans() {  
  2.     List<PersonBean> list = new ArrayList<PersonBean>();  
  3.     DocumentBuilderFactory builderFactory = DocumentBuilderFactory  
  4.             .newInstance();  
  5.     try {  
  6.         DocumentBuilder builder = builderFactory.newDocumentBuilder();  
  7.         Document document = builder.parse(DomPaserHelper.class  
  8.                 .getClassLoader().getResourceAsStream("person2.xml"));  
  9.         Element element = document.getDocumentElement();  
  10.         NodeList nodeList = element.getElementsByTagName("person");  
  11.   
  12.         for (int i = 0; i < nodeList.getLength(); i++) {  
  13.             Element node = (Element) nodeList.item(i);  
  14.             PersonBean bean = new PersonBean();  
  15.             bean.setId(Integer.valueOf(node.getAttribute("id")));  
  16.   
  17.             NodeList list2 = node.getChildNodes();  
  18.             for (int j = 0; j < list2.getLength(); j++) {  
  19.   
  20.                 Node element2 = list2.item(j);  
  21.   
  22.                 <span style="color:#ff6600;">// 判断子Note的类型为元素Note</span>  
  23.                 if (element2.getNodeType() == Node.ELEMENT_NODE) {  
  24.                     Element childElement = (Element) element2;  
  25.   
  26.                     if ("name".equals(childElement.getNodeName())) {  
  27.                         bean.setName(childElement.<span style="color:#ff6600;">getFirstChild</span>()  
  28.                                 .getNodeValue());  
  29.                     }  
  30.   
  31.                     if ("age".equals(childElement.getNodeName())) {  
  32.                         bean.setAge(childElement.<span style="color:#ff6600;">getFirstChild</span>()  
  33.                                 .getNodeValue());  
  34.                     }  
  35.                 }  
  36.             }  
  37.             list.add(bean);  
  38.         }  
  39.   
  40.     } catch (Exception e) {  
  41.         // TODO Auto-generated catch block  
  42.         e.printStackTrace();  
  43.     }  
  44.   
  45.     return list;  
  46. }  

二、PULL

[java] view plaincopy
  1. public static List<PersonBean> getPersonBeans() {  
  2.         List<PersonBean> list = null;  
  3.         boolean f = false;  
  4.         PersonBean bean = null;  
  5.         XmlPullParserFactory pullParserFactory;  
  6.         try {  
  7.   
  8.             pullParserFactory = XmlPullParserFactory.newInstance();  
  9.             XmlPullParser parser = pullParserFactory.newPullParser();  
  10.             parser.setInput(PullPaserHelper.class.getClassLoader()  
  11.                     .getResourceAsStream("person3.xml"), "utf-8");  
  12.             int tag = parser.getEventType();  
  13.             while (tag != XmlPullParser.END_DOCUMENT) {  
  14.                 switch (tag) {  
  15.                 case XmlPullParser.START_DOCUMENT:  
  16.                     list = new ArrayList<PersonBean>();  
  17.                     break;  
  18.                 case XmlPullParser.START_TAG:  
  19.                     String str = parser.getName();  
  20.   
  21.                     if (str.equals("person")) {  
  22.                         bean = new PersonBean();  
  23.                         bean.setId(Integer.valueOf(parser.getAttributeValue(0)));  
  24.                         f = true;  
  25.                     }  
  26.                     if (f&&bean!=null) {  
  27.                         if ("name".equals(str)) {  
  28.                             bean.setName(parser.nextText());  
  29.                         }  
  30.                         if ("age".equals(str)) {  
  31.                             bean.setAge(parser.nextText());  
  32.                         }  
  33.                     }  
  34.                     break;  
  35.                 case XmlPullParser.END_TAG:  
  36.                     String con = parser.getName();  
  37.                     if (con.equals("person") && bean != null) {  
  38.                         list.add(bean);  
  39.                         bean = null;  
  40.                         f = false;  
  41.                     }  
  42.   
  43.                     break;  
  44.   
  45.                 default:  
  46.                     break;  
  47.                 }  
  48.                 tag = parser.next();  
  49.   
  50.             }  
  51.   
  52.         } catch (Exception e) {  
  53.             // TODO Auto-generated catch block  
  54.             e.printStackTrace();  
  55.         }  
  56.   
  57.         return list;  
  58.     }  

首先,获取一个单例XmlPullParserFactory,然后newPullParser得到一个XmlPullParser对象。用setInput将服务器返回的xml设置进去,开始解析。通过getEventType得到int型的当前的解析对象,在while循环中不断进行解析,如果eventType不等于END_DOCUMENT,说明解析没完成,调用next()获取下一个解析事件继续解析。在while循环中,通过getName得到节点名字,用Switch进行判断,如果发现节点名字等于id或name,就用nextText获取节点内的具体内容。


三、SAX

[java] view plaincopy
  1. public class SaxHanderHelper extends DefaultHandler {  
  2.   
  3.     List<PersonBean> personBeans;  
  4.     String tag;  
  5.   
  6.     public List<PersonBean> getPersonBeans() {  
  7.         return personBeans;  
  8.     }  
  9.   
  10.     public SaxHanderHelper() {  
  11.         // TODO Auto-generated constructor stub  
  12.         personBeans = new ArrayList<PersonBean>();  
  13.     }  
  14.   
  15.     PersonBean bean;  
  16.   
  17.     @Override  
  18.     public void startElement(String uri, String localName, String qName,  //在这里获取标签和标签的属性  
  19.             Attributes attributes) throws SAXException {  //开始解析某个节点时调用
  20.         // TODO Auto-generated method stub  
  21.         if (localName.equals("person")) {  
  22.             bean = new PersonBean();  
  23.             for (int i = 0; i < attributes.getLength(); i++) {  
  24.                 bean.setId(Integer.valueOf(attributes.getValue(i)));  
  25.             }  
  26.         }  
  27.         tag = localName;  //记录当前节点名
  28.     }  
  29.   
  30.     @Override  
  31.     public void endElement(String uri, String localName, String qName)  
  32.             throws SAXException {  
  33.         // TODO Auto-generated method stub  
  34.         if (localName.equals("person") && bean != null) {  
  35.             personBeans.add(bean);  
  36.             bean = null;  
  37.         }  
  38.         tag = null;  
  39.     }  
  40.   
  41.     @Override  
  42.     public void characters(char[] ch, int start, int length)//在这里获取标签的值(获取节点中的内容)  
  43.             throws SAXException {  
  44.         // TODO Auto-generated method stub  
  45.         String content = new String(ch, start, length).trim();  
  46.         if (tag != null) {  
  47.             if (tag.equals("age")) {  
  48.                 bean.setAge(content);  
  49.             }  
  50.             if (tag.equals("name")) {  
  51.                 bean.setName(content);  
  52.             }  
  53.         }  
  54.   
  55.     }  
  56.   
  57. }  

首先,新建一个ContentHandler类继承自DefaultHandler,并重写5个方法。得到一个单例SAXParserFactory,调用facto的newSAXParser().getXMLReader()得到一个XMLReader对象。调用reader的setContentHandler并将handler传入。用parse开始执行解析。


调用方法:

[java] view plaincopy
  1. SAXParser saxParser = factory.newSAXParser();  
  2. SaxHanderHelper handerHelper = new SaxHanderHelper();  
  3. saxParser.parse(getInputStream(), handerHelper);  
  4. List<PersonBean> beans = handerHelper.getPersonBeans();  

0 0
原创粉丝点击