首页 > 解决方案 > XPath 语法进行排除某些特定元素的查询

问题描述

您可以在https://sabbiobet.netsons.org/test.html找到我的测试 html 页面

这是页面的 html 标记:

<table border="1" class="class_table">
    <tbody>
        <tr class="class_tr">
            <td class="class_td">&nbsp;</td>
        </tr>
        <tr class="class_tr">
            <td class="class_td"><span class="class_span_ok"></span>square</td>
        </tr>
        <tr class="class_tr">
            <td class="class_td"><span class="class_span_ko"></span>circle</td>
        </tr>
        <tr class="class_tr">
            <td class="class_td"><span class="class_span_ok"></span>triangle</td>
        </tr>
    </tbody>
</table>

我需要获取所有文本<td>class="class_td"减去那些文本为空或 &nbsp;有一个孩子<span>的文本class="class_ko"

换句话说,我只想获得这些值:

Square
Triangle

使用谷歌表格的 importXML 功能并遵循我尝试过的另一个用户的建议:

//td[@class='class_td' and span and not(span[@class='class_ko'])]

但只有当我在“span”和“/span”之间放置一些文本时它才有效

没有任何文本,我只会得到一个空结果。

有人可以帮助我吗?

标签: xpathgoogle-sheets-importxml

解决方案


如果通过将未定义的实体替换&nbsp;为等效的字符实体引用,将提供的格式不正确的文档更正&#xA0;为格式正确的文档:

<table border="1" class="class_table">
    <tbody>
        <tr class="class_tr">
            <td class="class_td">&#xA0;</td>
        </tr>
        <tr class="class_tr">
            <td class="class_td"><span class="class_span_ok"></span>square</td>
        </tr>
        <tr class="class_tr">
            <td class="class_td"><span class="class_span_ko"></span>circle</td>
        </tr>
        <tr class="class_tr">
            <td class="class_td"><span class="class_span_ok"></span>triangle</td>
        </tr>
    </tbody>
</table>

那么这个 XPath 表达式

/*/*/*/td [@class='class_td' and not(span[@class='class_span_ko']) and normalize-space(translate(., '&#xA0;', '')) ]/>

评估时,准确选择想要的td元素

<td class="class_td">
   <span class="class_span_ok"/>square</td>
<td class="class_td">
   <span class="class_span_ok"/>triangle</td>

基于 XSLT 的验证

此转换计算上述 XPath 表达式并将所选元素复制到输出:

<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=
    "/*/*/*/td
        [@class='class_td'
        and not(span[@class='class_span_ko'])
        and normalize-space(translate(., '&#xA0;', ''))
        ]"/>
  </xsl:template>
</xsl:stylesheet>

产生了想要的正确结果:

<td class="class_td">
   <span class="class_span_ok"/>square</td>
<td class="class_td">
   <span class="class_span_ok"/>triangle</td>

注意

如果只需要所需元素的字符串值,则 XPath 表达式可以是:

/*/*/*/td
    [@class='class_td'
    and not(span[@class='class_span_ko'])
    and normalize-space(translate(., '&#xA0;', ''))
    ]/text()

推荐阅读