使用XPath查询HTML文档

时间:2012-08-05 21:56:42

标签: c# html xpath

我有一个HTML文档,我想使用C#和XPath进行查询。我正在寻找的是一个XPath表达式 - 而不是XSLT,C#,PHP或任何其他语言特定的代码示例。任何帮助都将受到高度赞赏,但XPath表达式是我所需要的:)。

<tr>
  <td>
    <p>
      <span>text</span>
    </p>
  </td>
  <td>
    <p>
      <span>text</span>
    </p>
  </td>
</tr>
<tr>
  <td>
    <p>
      <span>This text is static and will never change</span>
    </p>
  </td>
  <td>
    <p>
      <span>Bla bla bla .... more bla bla bla</span>
    </p>
  </td>
</tr>
<tr>
  <td>
    <p>
      <span>text</span>
    </p>
  </td>
  <td>
    <p>
      <span>text</span>
    </p>
  </td>
</tr>

我正在寻找的XPath表达式将提取当前由字符串实例“Bla bla bla .... more bla bla bla”表示的文本。此文本将从HTML文档到HTML文档不等,但一个字符串始终相同。在这种情况下,该字符串表示为“此文本是静态的,永远不会更改”。

“这个文本是静态的,永远不会改变”和“Bla bla bla ...更多bla bla bla”当然不是真正的字符串 - 我替换它们因为它们是特定于域的,与问题无关他们揭示了不得出现的敏感数据!

同样,任何帮助都将受到高度赞赏。感谢。

1 个答案:

答案 0 :(得分:2)

使用

/*/tr[2]/td[2]/p/span/text()

当针对以下XML文档评估此XPath表达式时(通过将提供的格式错误的HTML转换为格式良好的XML文档获得):

<table>
    <tr>
        <td>
            <p>
                <span>text</span>
            </p>
        </td>
        <td>
            <p>
                <span>text</span>
            </p>
        </td>
    </tr>
    <tr>
        <td>
            <p>
                <span>Some text</span>
            </p>
        </td>
        <td>
            <p>
                <span>text to extract</span>
            </p>
        </td>
    </tr>
    <tr>
        <td>
            <p>
                <span>text</span>
            </p>
        </td>
        <td>
            <p>
                <span>text</span>
            </p>
        </td>
    </tr>
</table>

根据需要选择值为"text to extract"的文本节点

基于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="node()|@*">
     "<xsl:copy-of select="/*/tr[2]/td[2]/p/span/text()"/>"
 </xsl:template>
</xsl:stylesheet>

将此转换应用于同一XML文档(上图)时,将评估XPath表达式并将此评估的结果复制到输出

"text to extract"

或者,如果您知道文字但想要选择包含该文字的元素(例如td),请使用

//text()[. = 'text to extract']/ancestor::td[1]

再次使用基于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="node()|@*">
     <xsl:copy-of select=
      "//text()[. = 'text to extract']/ancestor::td[1]"/>
 </xsl:template>
</xsl:stylesheet>

结果现在是

<td>
   <p>
      <span>text to extract</span>
   </p>
</td>

又猜测

如果要查找最接近的前面的文本节点,请使用:

//text()[. = 'text to extract']/preceding::text()[1]

基于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="node()|@*">
     "<xsl:copy-of select=
      "//text()[. = 'text to extract']/preceding::text()[1]"/>"
 </xsl:template>
</xsl:stylesheet>

<强>结果

"Some text"

<强>更新

在OP的最新更新和他的新解释之后,他正在寻找的XPath表达式是:

//text()[. = 'This text is static and will never change']/following::text()[1]

这将选择具有字符串值的文本节点:

"Bla bla bla .... more bla bla bla"