加速xpath

jon*_*jon 18 java performance xpath nodelist nodes

我有一个1000条目文档,其格式类似于

<Example>
     <Entry>
          <n1></n1>
          <n2></n2>
      </Entry>
      <Entry>
          <n1></n1>
          <n2></n2>
      </Entry>
      <!--and so on-->
Run Code Online (Sandbox Code Playgroud)

这里有超过1000个Entry节点.我正在编写一个Java程序,它基本上逐个获取所有节点并对每个节点进行一些分析.但问题是节点的检索时间随着它的增加而增加.例如,检索第一个节点100毫秒以检索第二个节点需要78毫秒,并且它继续增加.要检索999节点,需要5秒以上.这非常慢.我们将此代码插入到包含超过1000个条目的XML文件中.有些像数百万.解析整个文档的总时间超过5分钟.

我正在使用这个简单的代码来遍历它.这nxp是我自己的类,它具有从xpath获取节点的所有方法.

nxp.fromXpathToNode("/Example/Entry" + "[" + i  + "]", doc);    
Run Code Online (Sandbox Code Playgroud)

并且doc是该文件的文档.i是要检索的节点的否.

当我尝试这样的事情时

List<Node> nl = nxp.fromXpathToNodes("/Example/Entry",doc);  
      content = nl.get(i);    
Run Code Online (Sandbox Code Playgroud)

我面临同样的问题.

任何人都有关于如何加速节点的tretirival的任何解决方案,因此从XML文件获取第一个节点以及1000个节点需要相同的时间.

谢谢


这是xpathtonode的代码.

public Node fromXpathToNode(String expression, Node context)  
{  
    try  
    {  
        return (Node)this.getCachedExpression(expression).evaluate(context, XPathConstants.NODE);  
    }  
    catch (Exception cause)  
    {  
        throw new RuntimeException(cause);  
    }  
}  
Run Code Online (Sandbox Code Playgroud)

这是fromxpathtonodes的代码.

public List<Node> fromXpathToNodes(String expression, Node context)  
{  
    List<Node> nodes = new ArrayList<Node>();  
    NodeList results = null;  

    try  
    {  
        results = (NodeList)this.getCachedExpression(expression).evaluate(context, XPathConstants.NODESET);  

        for (int index = 0; index < results.getLength(); index++)  
        {  
            nodes.add(results.item(index));  
        }  
    }  
    catch (Exception cause)  
    {  
        throw new RuntimeException(cause);  
    }  

    return nodes;  
}  
Run Code Online (Sandbox Code Playgroud)

这是开始

公共类NativeXpathEngine实现XpathEngine
{
private final XPathFactory factory;

private final XPath engine;  

/**
 * Cache for previously compiled XPath expressions. {@link XPathExpression#hashCode()}
 * is not reliable or consistent so use the textual representation instead.
 */  
private final Map<String, XPathExpression> cachedExpressions;  

public NativeXpathEngine()  
{
    super();  

    this.factory = XPathFactory.newInstance();  
    this.engine = factory.newXPath();  
    this.cachedExpressions = new HashMap<String, XPathExpression>();  
}  
Run Code Online (Sandbox Code Playgroud)

dog*_*ane 10

试试VTD-XML.它比DOM使用更少的内存.它比SAX更容易使用并支持XPath.以下是一些示例代码,可帮助您入门.它应用XPath来获取Entry元素,然后打印出n1和n2子元素.

final VTDGen vg = new VTDGen();
vg.parseFile("/path/to/file.xml", false);

final VTDNav vn = vg.getNav();
final AutoPilot ap = new AutoPilot(vn);
ap.selectXPath("/Example/Entry");
int count = 1;
while (ap.evalXPath() != -1) {
    System.out.println("Inside Entry: " + count);

    //move to n1 child
    vn.toElement(VTDNav.FIRST_CHILD, "n1");
    System.out.println("\tn1: " + vn.toNormalizedString(vn.getText()));

    //move to n2 child
    vn.toElement(VTDNav.NEXT_SIBLING, "n2");
    System.out.println("\tn2: " + vn.toNormalizedString(vn.getText()));

    //move back to parent
    vn.toElement(VTDNav.PARENT);
    count++;
}
Run Code Online (Sandbox Code Playgroud)

  • +1提到这个很棒的lib.我通过解析一些接近1分钟完成的xPathExpressions来遇到类似的问题.VTD-XML在2seks中完成相同的工作. (2认同)
  • 提到的图书馆真的很棒。根据用例,必须检查使用此 GPL 库传送代码是否具有法律依赖性,因为它建立在美国专利 7133857、7260652 和 7761459 之上。 (2认同)

小智 5

正确的解决方案是在调用item(i)之后立即分离节点,如下所示:

Node node = results.item(index)
node.getParentNode().removeChild(node)
nodes.add(node)
Run Code Online (Sandbox Code Playgroud)

请参阅XPath.evaluate性能在多个调用中减慢(荒谬)


Kan*_*ath 1

您使用什么类型的解析器?

DOM 将整个文档拉入内存 - 一旦将整个文档拉入内存,您的操作就会很快,但在 Web 应用程序或 for 循环中这样做可能会产生影响。

SAX 解析器按需解析并在您请求时加载节点。

因此,请尝试使用适合您需要的解析器实现。