2

我正在尝试从以下结构中提取数据:

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

我可以使用以下方法提取数据#1:

span[text()='Heading1']/following-sibling::br[1]/following::text()[1]

但我不知道如何提取 Heading4 下的数据。我需要提取data#4.1, data#4.2, data#4.3& data#4.4。点数不是固定的,可以变化。

4

4 回答 4

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 
于 2012-07-30T12:39:27.137 回答
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没有&acirc;&euro;&cent;before 的substring(.,5)函数,所以最终的 XPath 2 表达式变为:

(span[text()='Heading4']/following-sibling::text()[. != ""] except span[text()='Heading5']/following::text()[. != ""])/substring(., 5)

而且由于您没有明确说明您的语言要求,您可能还想查看我的基于 pascal 的查询语言,因为它是 imho 方式要好得多:

 <span>Heading4</span><br />
 <t:loop>
    {filter(text(), "data.*")}<br/>
 </t:loop>
 <br/>
 <span>Heading5</span><br />
于 2012-07-30T11:23:47.837 回答
1

在此处的答案的帮助下,我终于最终使用了它

//text()[preceding-sibling::span[1] = 'Heading4']

于 2012-07-30T12:02:25.690 回答
0

我会用

span[text()='Heading4']/following-sibling::text()

然后分别解析结果文本。

于 2012-07-30T11:01:43.150 回答