【问题标题】:XPath on DeferredDocumentImpl takes extremely long time to evaluateDeferredDocumentImpl 上的 XPath 需要很长时间来评估
【发布时间】:2018-07-25 07:45:01
【问题描述】:

在 Java 中,我从这样的文件加载一个 XML 文件,它返回一个 DeferredDocumentImpl

private Document loadMasterFileXml(String path)
{
    File masterFilePath = new File(path);
    DocumentBuilderFactory masterDocBuilderFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder masterDocBuilder = masterCbcCollBuilderFactory.newDocumentBuilder();
    masterDocument = masterDocBuilder.parse(masterFilePath);
    return masterDocument;
}

XML 文件包含大约 1000 个这样的元素:

<com.something.something.Collection xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:com.something.something.model="http://www.something.com/something.1.0.0" xmi:id="_HklwsJnWEeeaddrVFPWCMg" name="SOME_THING">
  <signals xmi:id="_N0ir0ZnWEeeaddrVFPWCMg" id="10000">
    <signal href="#_6M0edJhNEeeNvfntr9AQ8g"/>
  </signals>
  <signals xmi:id="_N0jS4JnWEeeaddrVFPWCMg" id="10001">
    <signal href="#_6M1FgJhNEeeNvfntr9AQ8g"/>
  </signals>
  ...

对该文档执行的第一个 XPath 操作如下:

public long getMaximumSignalIdFromMasterDocument()
{
    Integer errorCode=-1;
    try 
    {
        XPathFactory xPathfactory = XPathFactory.newInstance();
        XPath xPath = xPathfactory.newXPath();
        String expression = "//signals[not(@id < //signals/@id)]";
        Node node = (Node) xPath.evaluate(expression, masterCbCollDocument, XPathConstants.NODE);
        return Long.parseLong(node.getAttributes().getNamedItem("id").getNodeValue());
    }
    catch(Exception e) 
    {
        return errorCode;
    }        
}

在调试模式下,以下行需要 1 个多小时才能执行。

Node node = (Node) xPath.evaluate(expression, masterCbCollDocument, XPathConstants.NODE);

这是为什么?

XPath 表达式有问题吗(使用 //)? 是不是因为 Document 具体实现被推迟了,所以文件 IO 太多了?

谁能建议一种替代方法?

【问题讨论】:

  • 您特别想寻找什么信号?
  • 那个xpath应该返回最高的ID
  • 经过进一步调查,我注意到如果我在调试模式下断线并跨过它,xpath 只需要很长时间才能执行。如果我在该行之后放置一个断点,它会在正常时间执行。所以我想我可以解决这个问题。知道是什么原因造成的吗?
  • 这看起来更像是调试器的问题而不是实现。我已经根据您的模式生成了一个具有 1000 个信号元素的文件,并运行了您的表达式,结果会在一秒钟内显示出来。不过我猜计算时间会增长 N^2。

标签: java xml performance xpath


【解决方案1】:

另一种方法是避免使用 XPath。尽管长达一小时的计算似乎更可能成为您使用的调试器/IDE 的问题,但 XPath 表达式的效率也不是很高 (O(n^2)),并且无法在 XPath 1.0 中得到显着优化。在这种情况下直接使用 Java 似乎更合适。一种方法可能是:

NodeList signals = masterCbCollDocument.getElementsByTagName("signals");
long result = IntStream.range(0, signals.getLength()).mapToLong(i -> Long.parseLong(((Element)signals.item(i)).getAttribute("id"))).max().orElse(-1);

masterCbCollDocument.getElementsByTagName 在这种情况下与//signals XPath 表达式的作用相同。然后将 NodeList 中生成的 signal 元素映射到它们各自的 ID,并返回它们的最大值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-05-15
    • 1970-01-01
    • 2017-06-23
    • 1970-01-01
    • 2013-07-16
    • 2013-09-07
    • 2020-08-26
    相关资源
    最近更新 更多