【问题标题】:Use of text() function when using xPath in dom4j在 dom4j 中使用 xPath 时使用 text() 函数
【发布时间】:2012-03-28 19:38:22
【问题描述】:

我继承了一个使用 dom4j 和 xPath 解析 xml 的应用程序:

被解析的xml类似如下:

<cache>
  <content>
    <transaction>
      <page>
        <widget name="PAGE_ID">WRK_REGISTRATION</widget>
        <widget name="TRANS_DETAIL_ID">77145</widget>
        <widget name="GRD_ERRORS" />
      </page>
      <page>
        <widget name="PAGE_ID">WRK_REGISTRATION</widget>
        <widget name="TRANS_DETAIL_ID">77147</widget>
        <widget name="GRD_ERRORS" />
      </page>
      <page>
        <widget name="PAGE_ID">WRK_PROCESSING</widget>
        <widget name="TRANS_DETAIL_ID">77152</widget>
        <widget name="GRD_ERRORS" />
      </page>
    </transaction>
  </content>
</cache>

正在使用以下搜索单个节点:

String xPathToGridErrorNode = "//cache/content/transaction/page/widget[@name='PAGE_ID'][text()='WRK_DNA_REGISTRATION']/../widget[@name='TRANS_DETAIL_ID'][text()='77147']/../widget[@name='GRD_ERRORS_TEMP']";

org.dom4j.Element root = null;

SAXReader reader = new SAXReader();
Document document = reader.read(new BufferedInputStream(new ByteArrayInputStream(xmlToParse.getBytes())));
root = document.getRootElement();

Node gridNode = root.selectSingleNode(xPathToGridErrorNode);

其中 xmlToParse 是类似于上面提供的摘录的 xml 字符串。

代码正在尝试使用 xPath 中提供的 PAGE_ID 和 TRANS_DETAIL_ID 获取页面的 GRD_ERROR 节点。

我看到此 selectSingleNode 请求出现间歇性 (~1-2%) 失败(返回的节点为空),即使请求的节点位于正在搜索的 xml 中。

我知道在 xPath 中使用 text()= 存在一些问题,我想知道是否有更好的方法来格式化此类搜索的 xPath 字符串。

【问题讨论】:

  • 问题可能是由于树中存在碎片(相邻)文本节点。这不应该发生,但确实发生了:jira.codehaus.org/browse/JAXEN-67
  • 是的。您可以使用一些 XPath 魔法,例如 following-sibling:: 轴,或某种选择多个节点并对其进行处理,但此查询还不错,应该可以工作,并且如果不使用 @987654326 则不可替换@。我认为你最好的办法是更新到 dom4j v2.0.0 alpha 2 并希望问题会在那里消失。
  • 感谢您的意见。我知道 text() 的相邻文本节点问题,因此我们搜索的节点中的文本没有空格。我们正在使用 dom4j.1.6.1。此外,故障率约为千分之一,但仍会导致每天 2 或 3 个。在失败时,我们打印正在解析的 xml 和用于日志的 xPath。没有共同点 - 失败代表唯一的 xml 和 xPath 组合。我将尝试使用新的 dom4j v2.0.0。版本并报告我们的发现。
  • dom4jv2.0.0 是否解决了您的问题?我面临同样的事情:stackoverflow.com/questions/13607311/…

标签: xpath dom4j


【解决方案1】:

从您的 sn-ps 来看,GRD_ERRORSGRD_ERRORS_TMPWRK_REGISTRATIONWRK_DNA_REGISTRATION 之间存在问题。

忽略这一点,我建议重写

//cache/content/transaction/page
  /widget[@name='PAGE_ID'][text()='WRK_DNA_REGISTRATION']
  /../widget[@name='TRANS_DETAIL_ID'][text()='77147']
  /../widget[@name='GRD_ERRORS_TEMP']

作为

//cache/content/transaction/page
  [widget[@name='PAGE_ID'][text()='WRK_REGISTRATION']]
  [widget[@name='TRANS_DETAIL_ID'][text()='77147']]
  /widget[@name='GRD_ERRORS']

仅仅因为它使代码在我看来更易于阅读,并且更清楚地表达了您的意思:“page 元素具有具有这些条件的子元素,然后使用此 @987654328 获取小部件@。”或者,如果这更接近您的想法,

//cache/content/transaction/page/widget[@name='GRD_ERRORS']
  [preceding-sibling::widget[@name='PAGE_ID'][text()='WRK_REGISTRATION']]
  [preceding-sibling::widget[@name='TRANS_DETAIL_ID'][text()='77147']]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-16
    • 2020-01-24
    • 2014-07-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多