有很多类似的问题,但我找不到答案。
假设您有一个如下所示的 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
找到我A
和D
,现在我可以通过 JS ( document.querySelectorAll("query")[1]
) 或 Java(我最终使用这些元素)选择第二个元素。然而,使用额外的代码来完成通过选择器可以完成的工作是非常不一致的。
同样,我可以使用XPath 表达式:id('content')//td[1]
。它相当于上面的 CSS 选择器。它返回一个节点集,所以我认为 id('content')//td[1][2]
会按照我想要的方式工作,但运气不好。
过了一段时间,我发现( id('content')//td[1] )[2]
以我想要的方式工作,所以我就这么做了,并且对此感到非常满意。
尽管如此,我还是很失望,因为我无法执行单个查询来获取我的元素,因此出现了一个学术问题:是否有其他解决方案,无论是使用 CSS 选择器还是使用 XPath表达式来执行我的查询?我错过了什么?可以吗?
最佳答案
CSS 选择器目前不提供任何方法来选择一组全局匹配元素中的第 n 个元素或整个 DOM 中第 n 个出现的某个元素。 Selectors 3 提供的结构 :nth-*()
功能伪类和 Selectors 4所有都按其父级匹配条件的第 n 个子级进行计数,而不是按整个 DOM 中的第 n 个元素进行计数。
当前的选择器语法没有提供直观的方式来表示“这是 DOM 中一组匹配元素的第 n 个”;甚至 Selectors 4 中的 :nth-match()
和 :nth-last-match()
目前的语法也相当尴尬。所以这确实令人失望。
对于 XPath,要使用的表达式是 (id('content')//td[1])[2]
,正如您已经发现的那样。外部 ()
只是表示“整个子表达式应在 [2]
谓词之前求值”或“[2]
谓词应运行整个子表达式的结果,而不仅仅是 //td[1]
。”如果没有它们,表达式 td[1][2]
将被集中处理,两个相互冲突的谓词永远不会一起工作(不能让同一个元素同时成为第一个和第二个!)。
在子表达式两边加上括号并不会使它成为额外的查询本身;如果是,那么您可以考虑 id('content')
、//td
、[1]
和 [ 2]
本身也是一个“查询”,带有隐含(或可选)括号。这是很多查询:)
关于xpath - 选择页面上作为其父级的第 y 个子级的第 x 个元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14401146/