解析Xml文件的三种方式及其特点

Posted lucktian

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了解析Xml文件的三种方式及其特点相关的知识,希望对你有一定的参考价值。

1、Sax解析(simple api  for xml)

  使用流式处理的方式,它并不记录所读内容的相关信息。它是一种以事件为驱动的XML API,解析速度快,占用内存少。使用回调函数来实现。 

复制代码
 1     class MyDefaultHander extends  DefaultHandler{
 2         private List<Student> list;
 3         private  Student student;
 4 
 5         @Override
 6         public void startDocument() throws SAXException {
 7             super.startDocument();
 8             list=new ArrayList<>();
 9         }
10 
11         @Override
12         public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
13             super.startElement(uri, localName, qName, attributes);
14             if(qName.equals("student")){
15                 student=new Student();
16 
17         }
18             preTag=qName;
19         }
20 
21         @Override
22         public void endElement(String uri, String localName, String qName) throws SAXException {
23             if(qName.equals("student")){
24                 list.add(student);
25             }
26             preTag=null;
27         }
28 
29         @Override
30         public void characters(char[] ch, int start, int length) throws SAXException {
31             if(preTag!=null){
32                 if(preTag.equals("id")){
33                     student.setId(Integer.parseInt(new String(ch,start,length)));
34                 }else if(preTag.equals("name")){
35                     student.setName(new String(ch,start,length));
36                 }else if(preTag.equals("age")){
37                     student.setAge(Integer.parseInt(new String(ch,start,length)));
38                 }
39             }
40         }
41         public  List<Student> getStudents(){
42             return  list;
43         }
44     }
45   public  List<Student> sax_parser(){
46         List<Student> list=null;
47         try {
48             SAXParser parser= SAXParserFactory.newInstance().newSAXParser();
49             InputStream is= getAssets().open("student.xml");
50             MyDefaultHander hander=new MyDefaultHander();
51             parser.parse(is,hander);
52             list=  hander.getStudents();
53         } catch (ParserConfigurationException e) {
54             e.printStackTrace();
55         } catch (SAXException e) {
56             e.printStackTrace();
57         } catch (IOException e) {
58             e.printStackTrace();
59         }
60         return  list;
61     }
复制代码

2、Dom解析

  DOM(Document Object Model) 是一种用于XML文档的对象模型,可用于直接访问XML文档的各个部分。它是一次性全部将内容加载在内存中,生成一个树状结构,它没有涉及回调和复杂的状态管理。 缺点是加载大文档时效率低下

复制代码
 1     public  List<Student> DOM_parser(){
 2        DocumentBuilderFactory factory= DocumentBuilderFactory.newInstance();
 3         List<Student> list=null;
 4         try {
 5             Document dom= factory.newDocumentBuilder().parse(getAssets().open("student.xml"));
 6          Element element= dom.getDocumentElement();
 7          NodeList nodeList= element.getChildNodes();
 8             list=new ArrayList<>();
 9         for(int i=0;i<nodeList.getLength();i++){
10             Log.i(TAG, "DOM_parser: "+nodeList.item(i).getNodeName());
11            if(nodeList.item(i).getNodeName().equals("student")){
12                         NodeList childList= nodeList.item(i).getChildNodes();
13                        Student stu=new Student();
14                        for(int k=0;k<childList.getLength();k++){
15                           if(childList.item(k).getNodeName().equals("id")){
16                               stu.setId(Integer.parseInt(childList.item(k).getFirstChild().getNodeValue()));//注意直接getNodeValue()永远返回null,需调用getFirsetChild()后调用getNodeValue()
17                            }else if(childList.item(k).getNodeName().equals("name")){
18                                 stu.setName(childList.item(k).getFirstChild().getNodeValue());
19                            }else if(childList.item(k).getNodeName().equals("age")){
20                                stu.setAge(Integer.parseInt(childList.item(k).getFirstChild().getNodeValue()));
21                            }
22                        }
23                        list.add(stu);
24            }
25         }
26         } catch (SAXException e) {
27             e.printStackTrace();
28         } catch (IOException e) {
29             e.printStackTrace();
30         } catch (ParserConfigurationException e) {
31             e.printStackTrace();
32         }
33         return  list;
34     }
复制代码

3、pull解析(android 推荐)

  Pull内置于Android系统中。也是官方解析布局文件所使用的方式。Pull与SAX有点类似,都提供了类似的事件,如开始元素和结束元素。不同的是,SAX的事件驱动是回调相应方法,需要提供回调的方法,而后在SAX内部自动调用相应的方法。而Pull解析器并没有强制要求提供触发的方法。因为他触发的事件不是一个方法,而是一个数字。它使用方便,效率高

复制代码
 1     public  List<Student> Xml_pull_parser(){
 2         List<Student> list=null;
 3         XmlPullParser parser= Xml.newPullParser();
 4         try {
 5             parser.setInput(getAssets().open("student.xml"),"UTF-8");
 6            int event_code= parser.getEventType();
 7             Student student=null;
 8             while (event_code!=XmlPullParser.END_DOCUMENT){
 9                 switch (event_code){
10                     case XmlPullParser.START_DOCUMENT:
11                         list=new ArrayList<>();
12                         break;
13                     case  XmlPullParser.START_TAG:
14                         if(parser.getName().equals("student")){
15                             student=new Student();
16                         }
17                         if(student!=null){
18                         if(parser.getName().equals("id")){
19                           //  Log.i(TAG, "Xml_pull_parser: id="+parser.getText());
20                             student.setId( Integer.parseInt(parser.nextText()));
21                         }else if(parser.getName().equals("name")){
22                             student.setName(parser.nextText());
23                         }else if(parser.getName().equals("age")){
24                             student.setAge(Integer.parseInt(parser.nextText()));
25                         }
26                         }
27                         break;
28                     case  XmlPullParser.END_TAG:
29                         if(parser.getName().equals("student")){
30                             list.add(student);
31                             student=null;
32                         }
33                         break;
34                 }
35               event_code=  parser.next();
36 
37             }
38         } catch (XmlPullParserException e) {
39             e.printStackTrace();
40         } catch (IOException e) {
41             e.printStackTrace();
42         }
43         return  list;
44     }
 

 

DOM、SAX、PULL三类方式对比

DOM方式

  • 原理:基于文档驱动,是先把dom全部文件读入到内存中,构建一个主流内存的树结构,然后使用DOM的API遍历所有数据,调用API检索想要的数据和操作数据。
    所以,DOM方式的优缺点是:
  • 特点:
    优点:整个文档树存在内存中,可对XML文档进行操作:删除、修改等等;可多次访问已解析的文档;由于在内存中以树形结构存放,因此检索和更新效率会更高。;
    缺点:解析 XML 文件时会将整个 XML 文件的内容解析成树型结构存放在内存中并创建新对象,比较消耗时间和内存;
  • 使用情境
    对于像手机这样的移动设备来讲,内存是非常有限的,在XML文档比较小、需要对解析文档进行一定的操作且一旦解析了文档需要多次访问这些数据的情况下可以考虑使用DOM方式,因为其检索和解析效率较高

SAX方式

  • 原理:基于事件驱动,在读取XML文档内容时,事件源顺序地对文档进行扫描,当扫描到文档的开始与结束(Document)标签、节点元素的开始与结束(Element)标签时,直接调用对应的方法,并将状态信息以参数的形式传递到方法中,然后我们可以依据状态信息来执行相关的自定义操作。
  • 特点:
    优点:解析效率高、占存少、灵活性高
    缺点:解析方法复杂(API接口复杂),代码量大;可拓展性差:无法对 XML 树内容结构进行任何修改
  • 使用情境
    适用于需要处理大型 XML 文档、性能要求较高、不需要对解析文档进行修改且不需要对解析文档多次访问的场合

PULL方式

  • 原理:PULL的解析方式与SAX解析类似,都是基于事件的模式。
    PULL提供了开始元素和结束元素。当某个元素开始时,我们可以调用parser.nextText从XML文档中提取所有字符数据,与SAX不同的是,在PULL解析过程中触发相应的事件调用方法返回的是数字,且我们需要自己获取产生的事件然后做相应的操作,而不像SAX那样由处理器触发一种事件的方法从而执行代码。当解释到一个文档结束时,自动生成EndDocument事件。
  • 特点:
    优点:SAX的优点PULL都有,而且解析方法比SAX更加简单
    缺点:可拓展性差:无法对 XML 树内容结构进行任何修改

  • 使用情境
    适用于需要处理大型 XML 文档、性能要求较高、不需要对解析文档进行修改且不需要对解析文档多次访问的场合

同样的使用情景,在SAX和PULL解析方法中,更加推荐PULL方法

 

DOM、SAX、PULL三类方式对比

DOM方式

  • 原理:基于文档驱动,是先把dom全部文件读入到内存中,构建一个主流内存的树结构,然后使用DOM的API遍历所有数据,调用API检索想要的数据和操作数据。
    所以,DOM方式的优缺点是:
  • 特点:
    优点:整个文档树存在内存中,可对XML文档进行操作:删除、修改等等;可多次访问已解析的文档;由于在内存中以树形结构存放,因此检索和更新效率会更高。;
    缺点:解析 XML 文件时会将整个 XML 文件的内容解析成树型结构存放在内存中并创建新对象,比较消耗时间和内存;
  • 使用情境
    对于像手机这样的移动设备来讲,内存是非常有限的,在XML文档比较小、需要对解析文档进行一定的操作且一旦解析了文档需要多次访问这些数据的情况下可以考虑使用DOM方式,因为其检索和解析效率较高

SAX方式

  • 原理:基于事件驱动,在读取XML文档内容时,事件源顺序地对文档进行扫描,当扫描到文档的开始与结束(Document)标签、节点元素的开始与结束(Element)标签时,直接调用对应的方法,并将状态信息以参数的形式传递到方法中,然后我们可以依据状态信息来执行相关的自定义操作。
  • 特点:
    优点:解析效率高、占存少、灵活性高
    缺点:解析方法复杂(API接口复杂),代码量大;可拓展性差:无法对 XML 树内容结构进行任何修改
  • 使用情境
    适用于需要处理大型 XML 文档、性能要求较高、不需要对解析文档进行修改且不需要对解析文档多次访问的场合

PULL方式

  • 原理:PULL的解析方式与SAX解析类似,都是基于事件的模式。
    PULL提供了开始元素和结束元素。当某个元素开始时,我们可以调用parser.nextText从XML文档中提取所有字符数据,与SAX不同的是,在PULL解析过程中触发相应的事件调用方法返回的是数字,且我们需要自己获取产生的事件然后做相应的操作,而不像SAX那样由处理器触发一种事件的方法从而执行代码。当解释到一个文档结束时,自动生成EndDocument事件。
  • 特点:
    优点:SAX的优点PULL都有,而且解析方法比SAX更加简单
    缺点:可拓展性差:无法对 XML 树内容结构进行任何修改

  • 使用情境
    适用于需要处理大型 XML 文档、性能要求较高、不需要对解析文档进行修改且不需要对解析文档多次访问的场合

同样的使用情景,在SAX和PULL解析方法中,更加推荐PULL方法

以上是关于解析Xml文件的三种方式及其特点的主要内容,如果未能解决你的问题,请参考以下文章

Android解析XML文件的三种方式

git 忽略文件的三种方式

Android中的三种XML解析方式

PHP中Action的三种实现方式,struts.xml配置的详细解释及其简单执行过程

Qt中三种解析xml的方式

JSON的三种解析方式