Java中四种XML解析技巧

    添加时间:2013-5-25 点击量:

    在日常平凡工作中,不免会碰到把 XML 作为数据存储格局。面对今朝种类繁多的解决规划,哪个合适我们呢?在这篇文章中,我对这四种主流规划做一个不完全评测,仅仅针对遍历 XML 这块来测试,因为遍历 XML 是工作中应用最多的(至少我认为)。 


    预 备



    测试景象: 
      AMD 毒龙1.4G OC 1.5G、256M DDR333、Windows2000 Server SP4、Sun JDK 1.4.1+Eclipse 2.1+Resin 2.1.8,在 Debug 模式下测试。 
      XML 文件格局如下: 



     1    <?xml version=1.0 encoding=GB2312?> 
    
    2   <RESULT>
    3   <VALUE>
    4   <NO>A1234</NO>
    5   <ADDR>四川省XX县XX镇XX路X段XX号</ADDR>
    6   </VALUE>
    7   <VALUE>
    8   <NO>B1234</NO>
    9   <ADDR>四川省XX市XX乡XX村XX组</ADDR>
    10   </VALUE>
    11   </RESULT>


    测试办法: 
       采取 JSP 端调用Bean(至于为什么采取JSP来调用,请参考:http://blog.csdn.net/rosen/archive/2004/10/15 /138324.aspx),让每一种规划分别解析10K、100K、1000K、10000K的 XML 文件,策画其消费时候(单位:毫秒)。 
      JSP 文件: 



     1      <%@ page contentType=text/html; charset=gb2312 %> 
    
    2   <%@ page import=com.test.%>
    3
    4   <html>
    5   <body>
    6   <%
    7   String args[]={};
    8   MyXMLReader.main(args);
    9   %>
    10   </body>
    11   </html>


    测 试 

      起首出场的是 DOM(JAXP Crimson 解析器) 

       DOM 是用与平台和说话无关的体式格式默示 XML 文档的官方 W3C 标准。DOM 是以层次布局组织的节点或信息片段的凑集。这个层次布局容许开辟人员在树中寻找特定信息。解析该布局凡是须要加载全部文档和机关层次布局,然后才干做任何 工作。因为它是基于信息层次的,因而 DOM 被认为是基于树或基于对象的。DOM 以及广义的基于树的处理惩罚具有几个长处。起首,因为树在内存中是持久的,是以可以批改它以便应用法度能对数据和布局作出更改。它还可以在任何时辰在树中高低 导航,而不是像 SAX 那样是一次性的处理惩罚。DOM 应用起来也要简单得多。 

      另一方面,对于希罕大的文档,解析和加载全部文档可能很慢且很耗资料,是以应用其他手段来处理惩罚如许的数据会更好。这些基于事务的模型,比如 SAX。 

      Bean文件:



     1 package com.test; 
    
    2
    3   import java.io.;
    4   import java.util.;
    5   import org.w3c.dom.;
    6   import javax.xml.parsers.;
    7
    8   public class MyXMLReader{
    9
    10   public static void main(String arge[]){
    11   long lasting =System.currentTimeMillis();
    12   try{
    13    File f=new File(data_10k.xml);
    14    DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
    15    DocumentBuilder builder=factory.newDocumentBuilder();
    16    Document doc = builder.parse(f);
    17    NodeList nl = doc.getElementsByTagName(VALUE);
    18    forint i=0;i<nl.getLength();i++){
    19     System.out.print(车商标码: + doc.getElementsByTagName(NO).item(i).getFirstChild().getNodeValue());
    20     System.out.println( 车主地址: + doc.getElementsByTagName(ADDR).item(i).getFirstChild().getNodeValue());
    21   }
    22   }catch(Exception e){
    23    e.printStackTrace();
    24   }
    25   System.out.println(运行时候:+(System.currentTimeMillis() - lasting)+ 毫秒);
    26   }
    27   }



        //测试成果
    
    10k消费时候:265 203 219 172
      100k消费时候:
    9172 9016 8891 9000
      1000k消费时候:
    691719 675407 708375 739656
      10000k消费时候:OutOfMemoryError


    接着是 SAX 

       这种处理惩罚的长处很是类似于流媒体的长处。解析可以或许立即开端,而不是守候所有的数据被处理惩罚。并且,因为应用法度只是在读取数据时搜检数据,是以不须要将数 据存储在内存中。这对于大型文档来说是个重大的长处。事实上,应用法度甚至不必解析全部文档;它可以在某个前提获得满足时停止解析。一般来说,SAX 还比它的调换者 DOM 快很多。


       选择 DOM 还是选择 SAX ? 

      对于须要本身编写代码来处理惩罚 XML 文档的开辟人员来说,选择 DOM 还是 SAX 解析模型是一个很是首要的设计决定计划。 

      DOM 采取建树树形布局的体式格式接见 XML 文档,而 SAX 采取的事务模型。 

       DOM 解析器把 XML 文档转化为一个包含其内容的树,并可以对树进行遍历。用 DOM 解析模型的长处是编程轻易,开辟人员只须要调用建树的指令,然后哄骗navigation APIs接见所需的树节点来完成任务。可以很轻易的添加和批改树中的元素。然而因为应用 DOM 解析器的时辰须要处理惩罚全部 XML 文档,所以对机能和内存的请求斗劲高,尤其是碰到很大的 XML 文件的时辰。因为它的遍历才能,DOM 解析器常用于 XML 文档须要频繁的改变的办事中。 

      SAX 解析器采取了基于事务的模型,它在解析 XML 文档的时辰可以触发一系列的事务,当发明给定的tag的时辰,它可以激活一个回调办法,告诉该办法制订的标签已经找到。SAX 对内存的请求凡是会斗劲低,因为它让开辟人员本身来决意所要处理惩罚的tag。希罕是当开辟人员只须要处理惩罚文档中所包含的项目组数据时,SAX 这种扩大才能获得了更好的表现。但用 SAX 解析器的时辰编码工作会斗劲艰苦,并且很难同时接见同一个文档中的多处罚歧数据。


      Bean文件:




     1 package com.test; 
    
    2   import org.xml.sax.;
    3   import org.xml.sax.helpers.;
    4   import javax.xml.parsers.;
    5
    6   public class MyXMLReader extends DefaultHandler {
    7
    8   java.util.Stack tags = new java.util.Stack();
    9
    10   public MyXMLReader() {
    11   super();
    12   }
    13
    14   public static void main(String args[]) {
    15   long lasting = System.currentTimeMillis();
    16   try {
    17    SAXParserFactory sf = SAXParserFactory.newInstance();
    18    SAXParser sp = sf.newSAXParser();
    19    MyXMLReader reader = new MyXMLReader();
    20    sp.parse(new InputSource(data_10k.xml), reader);
    21   } catch (Exception e) {
    22    e.printStackTrace();
    23   }
    24   System.out.println(运行时候: + (System.currentTimeMillis() - lasting) + 毫秒);
    25   }
    26
    27   public void characters(char ch[], int start, int length) throws SAXException {
    28   String tag = (String) tags.peek();
    29   if (tag.equals(NO)) {
    30    System.out.print(车商标码: + new String(ch, start, length));
    31   }
    32   if (tag.equals(ADDR)) {
    33   System.out.println( 地址: + new String(ch, start, length));
    34   }
    35   }
    36
    37   public void startElement(
    38   String uri,
    39   String localName,
    40   String qName,
    41   Attributes attrs) {
    42   tags.push(qName);
    43   }
    44   }



    //测试成果
    
    10k消费时候:110 47 109 78
      100k消费时候:
    344 406 375 422
      1000k消费时候:
    3234 3281 3688 3312
      10000k消费时候:
    32578 34313 31797 31890 30328


    然后是 JDOM http://www.jdom.org/ 

       JDOM 的目标是成为 Java 特定文档模型,它简化与 XML 的交互并且比应用 DOM 实现更快。因为是第一个 Java 特定模型,JDOM 一向获得大力推广和促进。正在推敲经由过程“Java 规范恳求 JSR-102”将它终极用作“Java 标准扩大”。从 2000 年初就已经开端了 JDOM 开辟。 

      JDOM 与 DOM 首要有两方面不合。起首,JDOM 仅运器具体类而不应用接口。这在某些方面简化了 API,然则也限制了灵活性。第二,API 多量应用了 Collections 类,简化了那些已经熟悉这些类的 Java 开辟者的应用。 

       JDOM 文档声明其目标是“应用 20%(或更少)的精力解决 80%(或更多)Java/XML 题目”(按照进修曲线假定为 20%)。JDOM 对于大多半 Java/XML 应用法度来说当然是有效的,并且大多半开辟者发明 API 比 DOM 轻易懂得得多。JDOM 还包含对法度行动的相当广泛搜检以防止用户做任安在 XML 中无意义的事。然而,它仍须要您充沛懂得 XML 以便做一些超出根蒂根基的工作(或者甚至懂得某些景象下的错误)。这也许是比进修 DOM 或 JDOM 接口都更有意义的工作。 

       JDOM 自身不包含解析器。它凡是应用 SAX2 解析器来解析和验证输入 XML 文档(尽管它还可以将以前机关的 DOM 默示作为输入)。它包含一些转换器以将 JDOM 默示输出成 SAX2 事务流、DOM 模型或 XML 文本文档。JDOM 是在 Apache 容许证变体下公布的开放源码。 

      Bean文件:



     1 package com.test; 
    
    2
    3   import java.io.;
    4   import java.util.;
    5   import org.jdom.;
    6   import org.jdom.input.;
    7
    8   public class MyXMLReader {
    9
    10   public static void main(String arge[]) {
    11   long lasting = System.currentTimeMillis();
    12   try {
    13    SAXBuilder builder = new SAXBuilder();
    14    Document doc = builder.build(new File(data_10k.xml));
    15    Element foo = doc.getRootElement();
    16    List allChildren = foo.getChildren();
    17    forint i=0;i<allChildren.size();i++) {
    18     System.out.print(车商标码: + ((Element)allChildren.get(i)).getChild(NO).getText());
    19     System.out.println( 车主地址: + ((Element)allChildren.get(i)).getChild(ADDR).getText());
    20    }
    21   } catch (Exception e) {
    22    e.printStackTrace();
    23   }
    24   System.out.println(运行时候: + (System.currentTimeMillis() - lasting) + 毫秒);
    25   }
    26   }



    //测试成果
    
    10k消费时候:125 62 187 94
      100k消费时候:
    704 625 640 766
      1000k消费时候:
    27984 30750 27859 30656
      10000k消费时候:OutOfMemoryError


    最后是 DOM4J http://dom4j.sourceforge.net/ 

       固然 DOM4J 代表了完全自力的开辟成果,但最初,它是 JDOM 的一种智能分支。它归并了很多超出根蒂根基 XML 文档默示的功能,包含集成的 XPath 支撑、XML Schema 支撑以及用于大文档或流化文档的基于事务的处理惩罚。它还供给了构建文档默示的选项,它经由过程 DOM4J API 和标准 DOM 接口具有并行接见功能。从 2000 下半年开端,它就一向处于开辟之中。 

      为支撑所有这些功能,DOM4J 应用接口和抽象根蒂根基类办法。DOM4J 多量应用了 API 中的 Collections 类,然则在很多景象下,它还供给一些调换办法以容许更好的机能或更直接的编码办法。直接益处是,固然 DOM4J 付出了更错杂的 API 的价格,然则它供给了比 JDOM 大得多的灵活性。 

      在添加灵活性、XPath 集成和对大文档处理惩罚的目标时,DOM4J 的目标与 JDOM 是一样的:针对 Java 开辟者的易用性和直观操纵。它还致力于成为比 JDOM 更完全的解决规划,实如今本质上处理惩罚所有 Java/XML 题目的目标。在完成该目标时,它比 JDOM 更少夸大防止不正确的应用法度行动。 

      DOM4J 是一个很是很是优良的Java XML API,具有机能优良、功能强大和极端易用应用的特点,同时它也是一个开放源代码的软件。如今你可以看到越来越多的 Java 软件都在应用 DOM4J 来读写 XML,希罕值得一提的是连 Sun 的 JAXM 也在用 DOM4J。 

      Bean文件:



     1 package com.test; 
    
    2
    3   import java.io.;
    4   import java.util.;
    5   import org.dom4j.;
    6   import org.dom4j.io.;
    7
    8   public class MyXMLReader {
    9
    10   public static void main(String arge[]) {
    11   long lasting = System.currentTimeMillis();
    12   try {
    13    File f = new File(data_10k.xml);
    14    SAXReader reader = new SAXReader();
    15    Document doc = reader.read(f);
    16    Element root = doc.getRootElement();
    17    Element foo;
    18    for (Iterator i = root.elementIterator(VALUE); i.hasNext();) {
    19     foo = (Element) i.next();
    20     System.out.print(车商标码: + foo.elementText(NO));
    21     System.out.println( 车主地址: + foo.elementText(ADDR));
    22    }
    23   } catch (Exception e) {
    24    e.printStackTrace();
    25   }
    26   System.out.println(运行时候: + (System.currentTimeMillis() - lasting) + 毫秒);
    27   }
    28   }



    //测试成果
    
    10k消费时候:109 78 109 31
      100k消费时候:
    297 359 172 312
      1000k消费时候:
    2281 2359 2344 2469
      10000k消费时候:
    20938 19922 20031 21078


    JDOM 和 DOM 在机能测试时发挥解析不佳,在测试 10M 文档时内存溢出。在小文档景象下还值得推敲应用 DOM 和 JDOM。固然 JDOM 的开辟者已经申明他们期望在正式发行版前专注机能题目,然则从机能概念来看,它确切没有值得推荐之处。别的,DOM 还是一个很是好的选择。DOM 实现广泛应用于多种编程说话。它还是很多其它与 XML 相干的标准的根蒂根基,因为它正式获得 W3C 推荐(与基于非标准的 Java 模型相对),所以在某些类型的项目中可能也须要它(如在 JavaScript 中应用 DOM)。 

      SAX发挥解析较好,这要依附于它特定的解析体式格式。一个 SAX 检测即将到来的XML流,但并没有载入到内存(当然当XML流被读入时,会有项目组文档临时隐蔽在内存中)。 

      无疑,DOM4J是这场测试的获胜者,今朝很多开源项目中多量采取 DOM4J,例如大名鼎鼎的 Hibernate 也用 DOM4J 来读取 XML 设备文件。若是不推敲可移植性,那就采取DOM4J吧!


    原文出处:http://ss1.iteye.com/blog/514295

    彼此相爱,却不要让爱成了束缚:不如让它成为涌动的大海,两岸乃是你们的灵魂。互斟满杯,却不要同饮一杯。相赠面包,却不要共食一个。一起歌舞欢喜,却依然各自独立,相互交心,却不是让对方收藏。因为唯有生命之手,方能收容你们的心。站在一起却不要过于靠近。—— 纪伯伦《先知》
    分享到: