我该如何制定这个xpath表达式?

时间:2012-07-11 19:35:21

标签: xpath

给出以下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”检索span的内容。但是,我想要解析的一些div缺少第二个跨度(类“b”和“c”)。对于这些div,我希望span的内容与类“a”。是否可以创建一个选择它的单个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.)

3 个答案:

答案 0 :(得分: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>

答案 1 :(得分:1)

xpath表达式应该类似于:

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

union运算符|左边的表达式将选择所有div中的所有b-class spans,右边的表达式将首先查询没有b-class span的所有div然后选择他们的a级跨度。 |运算符结合了两组的结果。

请参阅here以选择不具有()和here的节点,以便将结果与|结合使用操作

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

返回的div中的所有内容
//div/node()

以便通过其他方式进行日后处理。

答案 2 :(得分:0)

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

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

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