【问题标题】:XPath with regex match on an attribute valueXPath 与属性值的正则表达式匹配
【发布时间】:2011-05-08 04:21:07
【问题描述】:

全部 -

为了破解这个问题,我已经搜索和修改了几个小时,但我仍然遇到问题。我有以下 XML 数据:

<game id="2009/05/02/arimlb-milmlb-1" pk="244539">
  <team id="109" name="Arizona" home_team="false">
    <event number="9" inning="1" description="Felipe Lopez doubles to left fielder Chris Duffy.  "/>
    <event number="15" inning="1" description="Augie Ojeda flies out to center fielder Mike Cameron.  "/>
    <event number="23" inning="1" description="Chad Tracy doubles to right fielder Joe Sanchez.  "/>
    <event number="52" inning="2" description="Mark Reynolds lines out to left fielder Chris Duffy.  "/>
    <!-- more data here -->
  </team>
</game>

我正在尝试获取在 description 属性的值中包含文本“doubles”的事件节点的总数。这是我到目前为止一直在尝试的方法,但无济于事(irb 抛出错误):

"/game/team/event/@description[matches(.,' doubles ')]"

因为我只是想匹配描述属性值的片段,所以可以使用 XPath 2.0 函数“匹配”,对吗?如果是这样,我做错了什么?

提前感谢您的帮助!

【问题讨论】:

  • 好问题,+1。请参阅我的答案以获得完整、简短且简单的单行 XPath 表达式解决方案:)
  • Mikecito - 我使用的是 Java 1.6,但我也使用 Ruby irb 进行开发和调试,例如 XPath。也就是说,我首先尝试在 irb 中使用 XPath 扫描文件,一旦我有一个得到我想要的 XPath,我会将它转移到我的 Java 代码中。
  • Dimitre - 您列出的 XPath 最终运行良好。我会在您的帖子下方单独发表评论。

标签: regex xpath attributes


【解决方案1】:

我正在尝试获取总数 包含文本的事件节点 ' doubles ' 的值 描述属性。

matches() 是标准的 XPath 2.0 函数。它在 XPath 1.0 中不可用

您可以使用

count(/*/*/event[contains(@description, ' doubles ')])

为了验证这一点,这里有一个小的 XSLT 转换,它只输出在提供的 XML 文档上评估上述 XPath 表达式的结果:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>


 <xsl:template match="/">
  <xsl:value-of select=
  "count(/*/*/event[contains(@description, ' doubles ')])"/>
 </xsl:template>
</xsl:stylesheet>

当此转换应用于提供的 XML 文档时:

<game id="2009/05/02/arimlb-milmlb-1" pk="244539">
    <team id="109" name="Arizona" home_team="false">
        <event number="9" inning="1" description="Felipe Lopez doubles to left fielder Chris Duffy.  "/>
        <event number="15" inning="1" description="Augie Ojeda flies out to center fielder Mike Cameron.  "/>
        <event number="23" inning="1" description="Chad Tracy doubles to right fielder Joe Sanchez.  "/>
        <event number="52" inning="2" description="Mark Reynolds lines out to left fielder Chris Duffy.  "/>
        <!-- more data here -->
    </team>
</game>

产生想要的正确结果

2

【讨论】:

  • Dimitre - 正如我上面提到的,您帖子中的 XPath 效果很好。我最终通过以下方式使其更加具体:"count(/game/team[@home_team='false']/event[contains(@description, ' doubles ')])" 非常感谢您的帮助!对此,我真的非常感激。显然,Java 1.6 不支持 XPath 2.0。
【解决方案2】:

尝试以下变体:

/game/team/event[matches(@description, ' doubles ')]/@description

/game/team/event[matches(@description, '^.*?doubles.*$')]/@description

/game/team/event[contains(@description, ' doubles ')]/@description

【讨论】:

  • 前两个在 Java 1.6 中尝试时不起作用,我怀疑是因为 XPath 2.0 显然不可用。第三个没有引起任何异常,但它似乎没有映射到所需的节点——返回的答案是 NaN。不过还是非常感谢。
【解决方案3】:

因为我只是想匹配一个 价值的片段 描述属性,有可能 使用 XPath 2.0 功能 '匹配',对吗?

可以,只要您使用 XPath 2.0 引擎来评估 XPath 表达式。

如果您要使用 XPath 2.0 引擎执行该 XPath,它将选择适当的 @description 属性。

如果是这样,我做错了什么?

如果您使用的是 XPath 2.0 引擎,您的问题可能是您已经选择了节点序列,但期望计数。

如果要返回这些属性的计数,可以使用count() 函数:

count(/game/team/event/@description[matches(.,' doubles ')])

【讨论】:

  • matchs() 函数在 Java 1.6 中似乎不可用(并不是我事先真的知道这一点)——它会引发 XPathExpressionException。不过还是谢谢!我很感激。
  • 标准 Java 1.6 库不支持 XPath 2.0,但 Saxon 和 PsychoPath 支持。
猜你喜欢
  • 1970-01-01
  • 2011-04-12
  • 1970-01-01
  • 2010-10-10
  • 2011-09-03
  • 2010-11-24
  • 2010-12-22
  • 1970-01-01
相关资源
最近更新 更多