我正在尝试从以下结构中提取数据:
<span>Heading</span>
<br />
<br />
<span>Heading1</span>
<br />
data#1
<br />
<br />
<span>Heading4</span><br />
• data#4.1
<br />
• data#4.2
<br />
• data#4.3
<br />
• data#4.4
<br />
<br />
<span>Heading5</span>
<br />
• data#5.1
<br />
• data#5.2
<br />
• data#5.3
<br />
<br />
我可以使用以下内容提取数据#1:
span[text()='Heading1']/following-sibling::br[1]/following::text()[1]
但我无法弄清楚如何在Heading4下提取数据。我需要提取data#4.1
,data#4.2
,data#4.3
&amp; data#4.4
。
积分数不固定,可能会有所不同。
答案 0 :(得分:3)
此XPath 1.0表达式精确选择所需节点:
/*/span[.='Heading4']
/following-sibling::text()
[count(.|/*/span[.='Heading5']/preceding-sibling::text())
=
count(/*/span[.='Heading5']/preceding-sibling::text())
]
[normalize-space()]
它是由着名的Kayessian方法生成的,用于交叉两个节点集$ns1
和$ns2
:
$ns1[count(.|$ns2) = count($ns2)]
如果在Kayessian公式中我们用$ns1
代替:
/*/span[.='Heading4']/following-sibling::text()
和$ns2
:
/*/span[.='Heading5']/preceding-sibling::text()
最终谓词[normalize-space()]
过滤掉此十字路口中仅有空白的文本节点。
基于XSLT的验证:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<xsl:copy-of select=
"/*/span[.='Heading4']
/following-sibling::text()
[count(.|/*/span[.='Heading5']/preceding-sibling::text())
=
count(/*/span[.='Heading5']/preceding-sibling::text())
]
[normalize-space()]
"/>
</xsl:template>
</xsl:stylesheet>
将此转换应用于提供的XML文档(替换实体 - 因为我们没有定义可用的DTD,这在此不重要):
<html>
<span>Heading</span>
<br />
<br />
<span>Heading1</span>
<br /> data#1
<br />
<br />
<span>Heading4</span>
<br /> #acirc;#euro;#cent; data#4.1
<br /> #acirc;#euro;#cent; data#4.2
<br /> #acirc;#euro;#cent; data#4.3
<br /> #acirc;#euro;#cent; data#4.4
<br />
<br />
<span>Heading5</span>
<br /> #acirc;#euro;#cent; data#5.1
<br /> #acirc;#euro;#cent; data#5.2
<br /> #acirc;#euro;#cent; data#5.3
<br />
<br />
</html>
评估Xpath表达式并将此评估结果复制到输出中:
#acirc;#euro;#cent; data#4.1
#acirc;#euro;#cent; data#4.2
#acirc;#euro;#cent; data#4.3
#acirc;#euro;#cent; data#4.4
答案 1 :(得分:2)
您可以使用
span[text()='Heading4']/following-sibling::text()[. != ""]
获取Heading4之后的所有文本,然后使用。
span[text()='Heading5']/following-sibling::text()[. != ""]
获取Heading5之后不需要的文本,然后从主程序中的第一个结果集中减去第二个结果集。
如果你有XPath 2,你可以直接用except
运算符排除它们:
span[text()='Heading4']/following-sibling::text()[. != ""] except span[text()='Heading5']/following::text()[. != ""]
使用data
函数之前,您只能获得•
而不是substring(.,5)
,因此最终的XPath 2表达式变为:
(span[text()='Heading4']/following-sibling::text()[. != ""] except span[text()='Heading5']/following::text()[. != ""])/substring(., 5)
由于你没有明确说出你的语言要求,你可能也想看看我的pascal based query language,因为它的方式更好:
<span>Heading4</span><br />
<t:loop>
{filter(text(), "data.*")}<br/>
</t:loop>
<br/>
<span>Heading5</span><br />
答案 2 :(得分:1)
我最终在答案here
的帮助下最终使用了这个 //text()[preceding-sibling::span[1] = 'Heading4']
答案 3 :(得分:0)
我用
span[text()='Heading4']/following-sibling::text()
然后单独解析生成的文本。