选择页面上的第x个元素,该元素是其父级的第y个子元素

时间:2013-01-18 14:36:31

标签: xpath css-selectors

有很多类似的问题,但我无法找到答案。

想象一下,你有一个这样的HTML页面:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8" />
        <title>Page title</title>
    </head>
    <body>
        <div id="content">
            <table>
                <tr>
                    <td>A</td>
                    <td>B</td>
                    <td>C</td>
                </tr>
                <tr>
                    <td>D</td>
                    <td>E</td>
                    <td>F</td>
                </tr>
            </table>
        </div>
    </body>
</html>

并且您希望选择页面上第二个<td>元素,该元素是其父的第一个子元素。在这种情况下,它是元素<td>D</td>

请注意,此措辞应保持不变,例如它与选择第二个<tr>然后选择第一个子元素(产生相同元素)不同,因为我正在处理的原始页面是比这个最小的测试用例复杂得多,这种方法在那里不起作用。

到目前为止我做了什么:

CSS选择器 #content td:first-child找到我AD,现在我可以通过JS选择第二个元素(document.querySelectorAll("query")[1] )或Java(我最终使用这些元素)。但是,使用附加代码来完成可以通过选择器完成的操作是非常不一致的。

同样,我可以使用 XPath表达式id('content')//td[1]。它相当于上面的CSS选择器。它返回一个节点集,所以我认为id('content')//td[1][2]将按照我想要的方式工作,但没有运气。

过了一段时间,我发现( id('content')//td[1] )[2]按照我想要的方式工作,所以我去了,我很满意。


尽管如此,看到我无法通过单个查询获取我的元素令我感到失望,因此出现了一个学术问题:是否有其他解决方案,无论是使用CSS选择器还是XPath表达式来做我的查询?我错过了什么?可以吗?

2 个答案:

答案 0 :(得分:2)

CSS选择器当前没有提供任何方法来选择一组全局匹配元素中的第n个元素或整个DOM中某个元素的第n个出现。 Selectors 3Selectors 4提供的结构:nth-*()功能伪类都由其父级的第n个子项与条件匹配,而不是由整个DOM中的第n个元素计数

当前的Selectors语法没有提供直观的方式来说明“这是DOM中一组匹配元素的第n个”;选择器4中的偶数:nth-match():nth-last-match()的语法非常笨拙。所以这确实令人失望。

对于XPath,正如您已经找到的那样,要使用的表达式为(id('content')//td[1])[2]。外部()只是意味着“应该在[2]谓词”之前评估整个子表达式,或者[2]谓词应该对整个子表达式的结果进行操作,而不仅仅是{{1} }“。如果没有它们,表达式//td[1]将被集体处理,两个冲突的谓词永远不会一起工作(你不能将相同的元素放在第一个和第二个!)。

在子表达式周围加括号不会使它成为额外的查询本身;如果是,那么您可以将td[1][2]id('content')//td[1]中的每一个视为“查询”,并且隐含< / em>(或可选)括号。这是很多疑问:)

答案 1 :(得分:1)

使用这个简单的XPath表达式:

(//td[1])[2]

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

在提供的XML文档上应用此转换时:

<html lang="en">
    <head>
        <meta charset="utf-8" />
        <title>Page title</title>
    </head>
    <body>
        <div id="content">
            <table>
                <tr>
                    <td>A</td>
                    <td>B</td>
                    <td>C</td>
                </tr>
                <tr>
                    <td>D</td>
                    <td>E</td>
                    <td>F</td>
                </tr>
            </table>
        </div>
    </body>
</html>

评估XPath表达式并将此评估结果复制到输出中:

<td>D</td>