【问题标题】:Querying HTML document using XPath使用 XPath 查询 HTML 文档
【发布时间】:2012-08-02 22:59:47
【问题描述】:

我有一个 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 文档而异,但一个字符串总是相同的。在这种情况下,该字符串表示为“此文本是静态的,永远不会改变”。

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

再次,我们将不胜感激任何帮助。谢谢。

【问题讨论】:

  • 使用什么语言——PHP? JavaScript?仅 HTML 无法做到这一点。请编辑问题以标记语言。
  • @Utkanos:XPath 表达式与语言无关。
  • 我知道这一点,但他/她将用某种语言实现它。他/她已将其重新标记为 C#。
  • 不一定。 xmlstarlet 等工具采用原始 XPath 表达式。
  • 如果您知道要查找的文本,为什么还要从文档中提取它?

标签: c# html xpath


【解决方案1】:

使用

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

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

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

还有一个猜测

如果你想找到最近的 preceding 文本节点,那么使用:

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

【讨论】:

  • 不幸的是[2]在这里太具体了;它需要锚定在“某些文本”上,而不是绝对位置。
  • 正如 Ignacio Vazquez-Abrahams 所说...这只是一个 HTML 示例,用于显示结构。在 2 个有趣的行之前或之后可能有一千行。结构当然是一样的。
  • @IgnacioVazquez-Abrams,看来你和我对这个问题有不同的理解。我将根据您的理解编辑答案并提供第二个表达方式。
  • @KevinJohnson,如果您知道要查找的文本,那么为什么需要从文档中提取它?
  • @DimitreNovaatchev 我只知道我要搜索的文本之前的内容。在这种情况下,它总是“一些文本”。但是字符串“要提取的文本”会因文档而异。
猜你喜欢
  • 2019-07-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-20
  • 2016-05-14
  • 2011-03-22
  • 2011-03-22
相关资源
最近更新 更多