JAVA通过XPath解析XML性能比较详解

最近在做一个小项目,使用到XML文件解析技术,通过对该技术的了解和使用,总结了以下内容。

1 XML文件解析的4种方法

通常解析XML文件有四种经典的方法。基本的解析方式有两种,一种叫SAX,另一种叫DOM。SAX是基于事件流的解析,DOM是基于XML文档树结构的解析。在此基础上,为了减少DOM、SAX的编码量,出现了JDOM,其优点是,20-80原则(帕累托法则),极大减少了代码量。通常情况下JDOM使用时满足要实现的功能简单,如解析、创建等要求。但在底层,JDOM还是使用SAX(最常用)、DOM、Xanan文档。另外一种是DOM4J,是一个非常非常优秀的Java XML API,具有性能优异、功能强大和极端易用的特点,同时它也是一个开放源代码的软件。如今你可以看到越来越多的 Java 软件都在使用 DOM4J 来读写 XML,特别值得一提的是连 Sun 的 JAXM 也在用 DOM4J。

2 XPath简单介绍

XPath 是一门在 XML 文档中查找信息的语言。XPath 用于在 XML 文档中通过元素和属性进行导航,并对元素和属性进行遍历。XPath 是 W3C XSLT 标准的主要元素,并且 XQuery 和 XPointer 同时被构建于 XPath 表达之上。因此,对 XPath 的理解是很多高级 XML 应用的基础。XPath非常类似对数据库操作的SQL语言,或者说JQuery,它可以方便开发者抓起文档中需要的东西。其中DOM4J也支持XPath的使用。

3 DOM4J使用XPath

DOM4J使用XPath解析XML文档是,首先需要在项目中引用两个JAR包:

dom4j-1.6.1.jar:DOM4J软件包,下载地址http://sourceforge.net/projects/dom4j/

jaxen-xx.xx.jar:通常不添加此包,会引发异常(java.lang.NoClassDefFoundError: org/jaxen/JaxenException),下载地址http://www.jaxen.org/releases.html

3.1 命名空间(namespace)的干扰

在处理由excel文件或其他格式文件转换的xml文件时,通常会遇到通过XPath解析得不到结果的情况。这种情况通常是由于命名空间的存在导致的。以下述内容的XML文件为例,通过XPath=" // Workbook/ Worksheet / Table / Row[1]/ Cell[1]/Data[1] "进行简单的检索,通常是没有结果出现的。这就是由于命名空间namespace(xmlns="urn:schemas-microsoft-com:office:spreadsheet")导致的。

<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:html="http://www.w3.org/TR/REC-html40">
 <Worksheet ss:Name="Sheet1">
  <Table ss:ExpandedColumnCount="81" ss:ExpandedRowCount="687" x:FullColumns="1" x:FullRows="1" ss:DefaultColumnWidth="52.5" ss:DefaultRowHeight="15.5625">
   <Row ss:AutoFitHeight="0">
     <Cell>
     <Data ss:Type="String">敲代码的耗子</Data>
     </Cell>
   </Row>
   <Row ss:AutoFitHeight="0">
     <Cell>
     <Data ss:Type="String">Sunny</Data>
     </Cell>
   </Row>
  </Table>
 </Worksheet>
</Workbook>

3.2 XPath对带有命名空间的xml文件解析

第一种方法(read1()函数):使用XPath语法中自带的local-name() 和 namespace-uri() 指定你要使用的节点名和命名空间。 XPath表达式书写较为麻烦。

第二种方法(read2()函数):设置XPath的命名空间,利用setNamespaceURIs()函数。

第三种方法(read3()函数):设置DocumentFactory()的命名空间 ,使用的函数是setXPathNamespaceURIs()。二和三两种方法的XPath表达式书写相对简单。

第四种方法(read4()函数):方法和第三种一样,但是XPath表达式不同(程序具体体现),主要是为了检验XPath表达式的不同,主要指完整程度,是否会对检索效率产生影响。(以上四种方法均通过DOM4J结合XPath对XML文件进行解析)

第五种方法(read5()函数):使用DOM结合XPath对XML文件进行解析,主要是为了检验性能差异。

没有什么能够比代码更能说明问题的了!果断上代码!

package XPath;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.XPath;
import org.dom4j.io.SAXReader;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

/**
 * DOM4J DOM XML XPath
 * @author hao
 */
public class TestDom4jXpath {
  public static void main(String[] args) {
    read1();
    read2();
    read3();
    read4();//read3()方法一样,但是XPath表达式不同
    read5();
  }

  public static void read1() {
    /*
     * use local-name() and namespace-uri() in XPath
     */
    try {
      long startTime=System.currentTimeMillis();
      SAXReader reader = new SAXReader();
      InputStream in = TestDom4jXpath.class.getClassLoader().getResourceAsStream("XPath\\XXX.xml");
      Document doc = reader.read(in);
      /*String xpath ="//*[local-name()='Workbook' and namespace-uri()='urn:schemas-microsoft-com:office:spreadsheet']"
          + "/*[local-name()='Worksheet']"
          + "/*[local-name()='Table']"
          + "/*[local-name()='Row'][4]"
          + "/*[local-name()='Cell'][3]"
          + "/*[local-name()='Data'][1]";*/
      String xpath ="//*[local-name()='Row'][4]/*[local-name()='Cell'][3]/*[local-name()='Data'][1]";
      System.err.println("=====use local-name() and namespace-uri() in XPath====");
      System.err.println("XPath:" + xpath);
      @SuppressWarnings("unchecked")
      List<Element> list = doc.selectNodes(xpath);
      for(Object o:list){
        Element e = (Element) o;
        String show=e.getStringValue();
        System.out.println("show = " + show);
      long endTime=System.currentTimeMillis();
      System.out.println("程序运行时间: "+(endTime-startTime)+"ms");
      }
    } catch (DocumentException e) {
      e.printStackTrace();
    }
  }

  public static void read2() {
    /*
     * set xpath namespace(setNamespaceURIs)
     */
    try {
      long startTime=System.currentTimeMillis();
      Map map = new HashMap();
      map.put("Workbook","urn:schemas-microsoft-com:office:spreadsheet");
      SAXReader reader = new SAXReader();
      InputStream in = TestDom4jXpath.class.getClassLoader().getResourceAsStream("XPath\\XXX.xml");
      Document doc = reader.read(in);
      String xpath ="//Workbook:Row[4]/Workbook:Cell[3]/Workbook:Data[1]";
      System.err.println("=====use setNamespaceURIs() to set xpath namespace====");
      System.err.println("XPath:" + xpath);
      XPath x = doc.createXPath(xpath);
      x.setNamespaceURIs(map);
      @SuppressWarnings("unchecked")
      List<Element> list = x.selectNodes(doc);
      for(Object o:list){
        Element e = (Element) o;
        String show=e.getStringValue();
        System.out.println("show = " + show);
      long endTime=System.currentTimeMillis();
      System.out.println("程序运行时间: "+(endTime-startTime)+"ms");
      }
    } catch (DocumentException e) {
      e.printStackTrace();
    }
  }

  public static void read3() {
    /*
     * set DocumentFactory() namespace(setXPathNamespaceURIs)
     */
    try {
      long startTime=System.currentTimeMillis();
      Map map = new HashMap();
      map.put("Workbook","urn:schemas-microsoft-com:office:spreadsheet");
      SAXReader reader = new SAXReader();
      InputStream in = TestDom4jXpath.class.getClassLoader().getResourceAsStream("XPath\\XXX.xml");
      reader.getDocumentFactory().setXPathNamespaceURIs(map);
      Document doc = reader.read(in);
      String xpath ="//Workbook:Row[4]/Workbook:Cell[3]/Workbook:Data[1]";
      System.err.println("=====use setXPathNamespaceURIs() to set DocumentFactory() namespace====");
      System.err.println("XPath:" + xpath);
      @SuppressWarnings("unchecked")
      List<Element> list = doc.selectNodes(xpath);
      for(Object o:list){
        Element e = (Element) o;
        String show=e.getStringValue();
        System.out.println("show = " + show);
      long endTime=System.currentTimeMillis();
      System.out.println("程序运行时间: "+(endTime-startTime)+"ms");
      }
    } catch (DocumentException e) {
      e.printStackTrace();
    }
  }

  public static void read4() {
    /*
     * 同read3()方法一样,但是XPath表达式不同
     */
    try {
      long startTime=System.currentTimeMillis();
      Map map = new HashMap();
      map.put("Workbook","urn:schemas-microsoft-com:office:spreadsheet");
      SAXReader reader = new SAXReader();
      InputStream in = TestDom4jXpath.class.getClassLoader().getResourceAsStream("XPath\\XXX.xml");
      reader.getDocumentFactory().setXPathNamespaceURIs(map);
      Document doc = reader.read(in);
      String xpath ="//Workbook:Worksheet/Workbook:Table/Workbook:Row[4]/Workbook:Cell[3]/Workbook:Data[1]";
      System.err.println("=====use setXPathNamespaceURIs() to set DocumentFactory() namespace====");
      System.err.println("XPath:" + xpath);
      @SuppressWarnings("unchecked")
      List<Element> list = doc.selectNodes(xpath);
      for(Object o:list){
        Element e = (Element) o;
        String show=e.getStringValue();
        System.out.println("show = " + show);
      long endTime=System.currentTimeMillis();
      System.out.println("程序运行时间: "+(endTime-startTime)+"ms");
      }
    } catch (DocumentException e) {
      e.printStackTrace();
    }
  }

  public static void read5() {
    /*
     * DOM and XPath
     */
    try {
      long startTime=System.currentTimeMillis();
      DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
      dbf.setNamespaceAware(false);
      DocumentBuilder builder = dbf.newDocumentBuilder();
      InputStream in = TestDom4jXpath.class.getClassLoader().getResourceAsStream("XPath\\XXX.xml");
      org.w3c.dom.Document doc = builder.parse(in);
      XPathFactory factory = XPathFactory.newInstance();
      javax.xml.xpath.XPath x = factory.newXPath();
      //选取所有class元素的name属性
      String xpath = "//Workbook/Worksheet/Table/Row[4]/Cell[3]/Data[1]";
      System.err.println("=====Dom XPath====");
      System.err.println("XPath:" + xpath);
      XPathExpression expr = x.compile(xpath);
      NodeList nodes = (NodeList)expr.evaluate(doc, XPathConstants.NODE);
      for(int i = 0; i<nodes.getLength();i++) {
        System.out.println("show = " + nodes.item(i).getNodeValue());
      long endTime=System.currentTimeMillis();
      System.out.println("程序运行时间: "+(endTime-startTime)+"ms");
      }
    } catch(XPathExpressionException e) {
      e.printStackTrace();
    } catch(ParserConfigurationException e) {
      e.printStackTrace();
    } catch(SAXException e) {
      e.printStackTrace();
    } catch(IOException e) {
      e.printStackTrace();
    }
  }
}

3.3 不同方法的性能比较

为了比较几种方法的解析性能,实验过程中使用了6M以上大小,7万行以上的XML文件(XXX.xml)进行10轮测试,如下所述:

图1 XPath使用性能对比


方法名称


平均运行时间


XPath表达式


read1()


1663ms


//*[local-name()='Row'][4]/*[local-name()='Cell'][3]/*[local-name()='Data'][1]


read2()


2184ms


//Workbook:Row[4]/Workbook:Cell[3]/Workbook:Data[1]


read3()


601ms


//Workbook:Row[4]/Workbook:Cell[3]/Workbook:Data[1]


read4()


472ms


//Workbook:Worksheet/Workbook:Table/Workbook:Row[4]/Workbook:Cell[3]/Workbook:Data[1]


read5()


1094ms


//Workbook/Worksheet/Table/Row[4]/Cell[3]/Data[1]

表1 平均性能统计

由以上性能对比可知:

1、read4()方法运行时间最短,即运用DOM4J方法调用全路径(从根节点出发)XPath表达式解析XML文件耗时最短;

2、运用DOM解析方法所使用的XPath表达式最为简单(可以写作//Row[4]/Cell[3]/Data[1]),因DOM中可以通过setNamespaceAware(false)方法使命名空间失效。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • java实现利用String类的简单方法读取xml文件中某个标签中的内容

    1.利用String类提供的indexOf()和substring()快速的获得某个文件中的特定内容 public static void main(String[] args) { // 测试某个词出现的位置 String reqMessage = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>" + "<in>" + "<head&g

  • Java对象的XML序列化与反序列化实例解析

    上一篇文章我们介绍了java实现的各种排序算法代码示例,本文我们看看Java对象的xml序列化与反序列化的相关内容,具体如下. XML是一种标准的数据交换规范,可以方便地用于在应用之间交换各类数据.如果能在Java对象和XML文档之间建立某种映射,例如Java对象的XML序列化和反序列化,那么就可以使Java的对象方便地与其他应用进行交换. java.beans包里面有两个类XMLEncoder和Decoder,分别用于将符合JabaBeans规范的Java对象以XML方式序列化和反序列化.以下

  • Java开发中读取XML与properties配置文件的方法

    相关阅读: 使用Ajax进行文件与其他参数的上传功能(java开发) 1. XML文件: 什么是XML?XML一般是指可扩展标记语言,标准通用标记语言的子集,是一种用于标记电子文件使其具有结构性的标记语言. 2.XML文件的优点: 1)XML文档内容和结构完全分离. 2)互操作性强. 3)规范统一. 4)支持多种编码. 5)可扩展性强. 3.如何解析XML文档: XML在不同的语言中解析XML文档都是一样的,只不过实现的语法不一样,基本的解析方式有两种,一种是SAX方式,是按照XML文件的顺序一

  • java 与testng利用XML做数据源的数据驱动示例详解

    java 与testng利用XML做数据源的数据驱动示例详解 testng的功能很强大,利用@DataProvider可以做数据驱动,数据源文件可以是EXCEL,XML,YAML,甚至可以是TXT文本.在这以XML为例: 备注:@DataProvider的返回值类型只能是Object[][]与Iterator<Object>[] TestData.xml: <?xml version="1.0" encoding="UTF-8"?> <

  • java实现XML增加元素操作简单示例

    本文实例讲述了java实现XML增加元素操作.分享给大家供大家参考,具体如下: package Day01; import java.io.*; import javax.xml.parsers.*; import javax.xml.transform.*; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.w3c.dom.*; public

  • JAVA通过XPath解析XML性能比较详解

    最近在做一个小项目,使用到XML文件解析技术,通过对该技术的了解和使用,总结了以下内容. 1 XML文件解析的4种方法 通常解析XML文件有四种经典的方法.基本的解析方式有两种,一种叫SAX,另一种叫DOM.SAX是基于事件流的解析,DOM是基于XML文档树结构的解析.在此基础上,为了减少DOM.SAX的编码量,出现了JDOM,其优点是,20-80原则(帕累托法则),极大减少了代码量.通常情况下JDOM使用时满足要实现的功能简单,如解析.创建等要求.但在底层,JDOM还是使用SAX(最常用).D

  • PHP使用xpath解析XML的方法详解

    本文实例讲述了PHP使用xpath解析XML的方法.分享给大家供大家参考,具体如下: XML文件在PHP网站开发的轻量级应用中使用非常广泛,而PHP解析和读取XML文件的方式有很多种,比如JS DOM.SimpleXml.Xpath等方式解析XML文件,今天来讲讲在PHP中使用Xpath解析XML的实例,同时通过Xpath解析XML的实例来介绍部分基础的Xpath语法. Xpath是什么? Xapth主要用来在XML文档中查询信息的工具,通过使用路径表达式可以解析XML文件,读取XML文件中的数

  • JAVA DOM解析XML文件过程详解

    这篇文章主要介绍了JAVA DOM解析XML文件过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 代码如下 import java.io.IOException; import javax.xml.parsers.*; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.No

  • java 中maven pom.xml文件教程详解

    maven pom.xml文件教程详解,具体内容如下所示: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.x

  • java 中HttpClient传输xml字符串实例详解

    java 中HttpClient传输xml字符串实例详解 介绍:我现在有一个对象page,需要将page对象转换为xml格式并以binary方式传输到服务端 其中涉及到的技术点有: 1.对象转xml流 2.输出流转输入流 3.httpClient发送二进制流数据 POM文件依赖配置 <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifact

  • Java使用JSONPath解析JSON完整内容详解

    JsonPath是一种简单的方法来提取给定JSON文档的部分内容. JsonPath有许多编程语言,如Javascript,Python和PHP,Java. JsonPath提供的json解析非常强大,它提供了类似正则表达式的语法,基本上可以满足所有你想要获得的json内容. maven中添加jar包 JsonPath可在Central Maven存储库中找到. Maven用户将其添加到您的POM. com.jayway.jsonpath json-path 2.2.0 操作符 操作 说明 $

  • java使用xpath解析xml示例分享

    XPath即为XML路径语言(XML Path Language),它是一种用来确定XML文档中某部分位置的语言.XPath基于XML的树状结构,提供在数据结构树中找寻节点的能力.起初 XPath 的提出的初衷是将其作为一个通用的.介于XPointer与XSL间的语法模型.但是 XPath 很快的被开发者采用来当作小型查询语言. XPathTest.java 复制代码 代码如下: package com.hongyuan.test; import java.io.File;import java

  • Android基于Pull方式解析xml的方法详解

    本文实例讲述了Android基于Pull方式解析xml的方法.分享给大家供大家参考,具体如下: Pull解析和Sax解析很相似,都是轻量级的解析,在Android的内核中已经嵌入了Pull,所以我们不需要再添加第三方jar包来支持Pull. Pull解析和Sax解析不一样的地方有: (1)pull读取xml文件后触发相应的事件调用方法返回的是数字 (2)pull可以在程序中控制想解析到哪里就可以停止解析. 来看看实例: book.xml如下: <?xml version="1.0"

  • Android编程创建与解析xml的常用方法详解

    本文实例讲述了Android编程创建与解析xml的常用方法.分享给大家供大家参考,具体如下: 今天我今天给大家讲解一下Android创建xml以及一些解析xml的常用方法. 首先是创建,我们用XmlSerializer这个类来创建一个xml文件,其次是解析xml文件,常用的有dom,sax,XmlPullParser等方法,由于sax代码有点复杂,本节只讲解一下dom与XmlPullParser解析,sax我将会在下一节单独讲解,至于几种解析xml的优缺点我就不再讲述了. 为了方便理解,我做了一

  • php解析xml方法实例详解

    本文以实例形式详细讲述了php解析xml方法.分享给大家供大家参考.具体分析如下: books.xml文件如下: <?xml version="1.0" encoding="ISO-8859-1"?> <bookstore> <book category="children"> <title lang="en">Harry Potter</title> <aut

随机推荐