给出以下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.)
答案 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的答案。