比javax.xml.xpath更快的api来解析xml的值?

时间:2011-06-24 17:57:35

标签: java xml

我正在使用javax.xml.xpath来搜索xml文件中的特定字符串,但由于需要搜索大量的xml文件,因此结果比预期慢得多。

java支持的api是否比javax.xml.xpath更快或哪个是最快的?

4 个答案:

答案 0 :(得分:10)

正如skaffman所指出的那样,您需要确保尽可能高效地使用javax.xml.xpath库。如果您要执行XPath语句,则需要确保将其编译为XPathExpression

XPathExpression xPathExpression = xPath.compile("/root/device/modelname");
nl = (NodeList) xPathExpression.evaluate(dDoc, XPathConstants.NODESET);

<强>演示

在示例中,选项#2将比选项#1更快。

import java.io.File;

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

import org.w3c.dom.Document;
import org.w3c.dom.NodeList;

public class Demo {

    public static void main(String[] args) {
        DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
        try {
            DocumentBuilder builder = domFactory.newDocumentBuilder();
            File xml = new File("input.xml");
            Document dDoc = builder.parse(xml);

            NodeList nl;

            // OPTION #1
            XPath xPath = XPathFactory.newInstance().newXPath();
            nl = (NodeList) xPath.evaluate("root/device/modelname", dDoc, XPathConstants.NODESET);
            printResults(nl);
            nl = (NodeList) xPath.evaluate("/root/device/modelname", dDoc, XPathConstants.NODESET);
            printResults(nl);

            // OPTION #2
            XPathExpression xPathExpression = xPath.compile("/root/device/modelname");
            nl = (NodeList) xPathExpression.evaluate(dDoc, XPathConstants.NODESET);
            printResults(nl);
            nl = (NodeList) xPathExpression.evaluate(dDoc, XPathConstants.NODESET);
            printResults(nl);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void printResults(NodeList nl) {
        for(int x=0; x<nl.getLength(); x++) {
            System.out.println("the value is: " + nl.item(x).getTextContent());
        }
    }

}

<强> input.xml中

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <blah>foo</blah>
  <device>
    <modelname>xbox</modelname>
  </device>
  <blah>bar</blah>
  <device>
    <modelname>wii</modelname>
  </device>
  <blah/>
</root>

答案 1 :(得分:4)

我想知道XPath搜索是否真的是你的瓶颈,还是它实际上是XML解析?我会怀疑后者。我不知道您的XML文档是多么持久,但我认为解决方案是将它们存储在XML数据库中,这样您只需要产生一次解析成本,这样就可以将它们编入索引以使XPath / XQuery搜索更有效率

答案 2 :(得分:1)

你可以查看我之前的answer相关内容。

基本上我使用了JXpath和Xerces以及Dom4J和javax。 我可以从我的经验中充满信心地说VTD-XML是最快的选择。

如果你想搜索,还有很多其他关于在SO上使用VTD-XML的问题。

编辑:
好的,所以基于你的评论,代码片段将是这样的:

VTDGen vg = new VTDGen();
AutoPilot ap = new AutoPilot();
int i;
ap.selectXPath("/root/device/modelname");
if (vg.parseFile(PATH_TO_FILE,true)){
    VTDNav vn = vg.getNav();
    ap.bind(vn); // apply XPath to the VTDNav instance
    // AutoPilot moves the cursor for you
    while((i=ap.evalXPath())!=-1){
        System.out.println("the value is: " + vn.toNormalizedString(vn.getText()));
    }
}

对于以下XML:

<root>
  <blah>foo</blah>
  <device>
    <modelname>xbox</modelname>
  </device>
  <blah>bar</blah>
  <device>
    <modelname>wii</modelname>
  </device>
  <blah/>
</root>

输出将是:

the value is: xbox
the value is: wii

你可以从这里拿走......

答案 3 :(得分:0)

你应该详细说明你要搜索的是什么类型的东西 - 如果它是简单的内容字符串,我会考虑使用Stax API(javax.xml.stream.XMLStreamReader)。 如果您需要限制搜索特定子集,则XPath很好。

XPath的一个问题是,依赖于表达式,它最终可能会在内存中构建一个DOM树,而且这在速度和内存使用方面都相当昂贵(相对于解析XML)。因此,如果可以避免这种情况,单独就可以加快3x工厂的处理速度。