3

给定以下 div 元素

<div class="info">
    <a href="/s/xyz.html" class="title">title</a>
    <span class="a">123</span>
    <span class="b">456</span>
    <span class="c">789</span>
</div>

我想用“b”类检索跨度的内容。但是,我要解析的一些 div 缺少后两个跨度(“b”类和“c”类)。对于这些 div,我想要“a”类的 span 的内容。是否可以创建一个选择它的 XPath 表达式?

如果不可能,是否可以创建一个检索 div 全部内容的选择器?即检索

<a href="/s/xyz.html" class="title">title</a>
<span class="a">123</span>
<span class="b">456</span>
<span class="c">789</span>

如果我能做到这一点,我可以使用正则表达式来查找我想要的数据。(我可以选择 div 中的文本,但我也不确定如何选择标签。只有文本会产生 123456789。)

4

3 回答 3

2

更高效——不需要联合

   //div/span
          [@class='b'
           or
             @class='a'
            and
             not(parent::*[span[@class='b']])
           ]

作为两个绝对“//表达式”的并集的表达式(如下所示),通常执行两个完整的文档树遍历,然后联合操作按文档顺序执行重复数据删除和排序——所有这些都可能比单个操作效率低得多树遍历,除非 XPath 处理器具有智能优化器。

这种低效表达的一个例子

//div/span[@class='b'] | //div[not(./span[@class='b'])]/span[@class='a'] 

基于 XSLT 的验证

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="/">
  <xsl:copy-of select=
  "//div/span
          [@class='b'
           or
             @class='a'
            and
             not(parent::*[span[@class='b']])
           ]"/>
 </xsl:template>
</xsl:stylesheet>

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

<div class="info">
    <a href="/s/xyz.html" class="title">title</a>
    <span class="a">123</span>
    <span class="b">456</span>
    <span class="c">789</span>
</div>

计算 Xpath 表达式,并将选定的元素(在本例中只有一个)复制到输出

<span class="b">456</span>

当相同的转换应用于不同的 XML 文档时,其中没有class='b'

<div class="info">
    <a href="/s/xyz.html" class="title">title</a>
    <span class="a">123</span>
    <span class="x">456</span>
    <span class="c">789</span>
</div>

评估相同的 XPath 表达式并将正确选择的元素复制到输出

<span class="a">123</span>
于 2012-07-12T15:42:33.820 回答
1

xpath 表达式应该类似于:

//div/span[@class='b'] | //div[not(./span[@class='b'])]/span[@class='a']

union 运算符左侧的表达式|将选择所有 div 中的所有 b-class span,右侧的表达式将首先查询没有 b-class span 的所有 div,然后选择它们的 a-class span。该| 运算符将两个集合的结果结合起来。

请参阅此处以使用 not() 选择节点,并查看此处以将结果与 | 操作员。

另外,要参考您问题的第二部分,请查看此处。在 xpath 中使用 node() 您可以选择所选节点下方的所有内容(节点 + 文本)。所以你可以得到 div 返回的所有内容

//div/node()

以供将来通过其他方式处理。

于 2012-07-11T19:47:44.000 回答
0

在没有联合运算符的情况下对您的输入起作用的表达式:

//div/span[@class='a' or @class='b'][count(../span[@class='b']) + 1]

这只是为了好玩。我可能会在生产代码中使用更像@inVader 的答案。

于 2012-07-11T21:15:17.540 回答