我如何表述这个xpath表达式?

我如何表述这个xpath表达式?,xpath,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检索spa

给定以下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,我想要类a的span的内容。可以创建一个XPath表达式来选择它吗

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

<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。

xpath表达式应该类似于:

//div/span[@class='b'] | //div[not(./span[@class='b'])]/span[@class='a']
联合运算符|左侧的表达式将选择所有div中的所有b类跨距,右侧的表达式将首先查询没有b类跨距的所有div,然后选择它们的a类跨距。|运算符将两个集合的结果组合在一起

有关使用not选择节点以及使用|运算符组合结果的信息,请参见

另外,请参阅问题的第二部分。 使用xpath中的节点,可以选择所选节点下方的所有节点+文本。这样你就可以把div里的所有东西

//div/node()

用于将来通过其他方式进行处理。

一种不使用union运算符处理输入的表达式:

//div/span[@class='a' or @class='b'][count(../span[@class='b']) + 1]
这只是为了好玩。我可能会在生产代码中使用更像@inVader的答案。

更高效-不需要联合:

下面的表达式是两个绝对//表达式的并集,通常执行两次完整的文档树遍历,然后并集操作按文档顺序执行重复数据消除和排序-所有这些都可能比单个树遍历效率低得多,除非XPath处理器有智能优化器

这种低效表达的一个例子:

基于XSLT的验证:

计算相同的XPath表达式,并将正确选择的元素复制到输出:


谢谢,这很有启发性。我注意到notspan[@class='b']似乎不起作用。/span[@class='b']前者是您提供的not链接的语法。这两者之间有区别吗?我上次使用xpath已经有一段时间了,为了安全起见,我从链接中复制了xpath。我认为在Requirrang中span[@class='b']必须是div的直接子级,这应该是等价的。如果您使用//另一方面,您将在DOM中得到div下面的任何span[@class='b'],即使它是子级的子级。但是,如果您想确定,请更详细地查看w3school链接中的xpath手册。
   //div/span
          [@class='b'
           or
             @class='a'
            and
             not(parent::*[span[@class='b']])
           ]
//div/span[@class='b'] | //div[not(./span[@class='b'])]/span[@class='a'] 
<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>
<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>
<span class="b">456</span>
<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>
<span class="a">123</span>