Html 使用XPath为节点的每个子节点获取第一个子节点
我试图用以下结构解析一些HTML,如何使用xpath提取每个Html 使用XPath为节点的每个子节点获取第一个子节点,html,xpath,Html,Xpath,我试图用以下结构解析一些HTML,如何使用xpath提取每个元素的第一个元素 <ul> <li> <a> <span> <a> </li> <li> <a> <span> <a> </li> ... </ul>
元素的第一个元素
<ul>
<li>
<a>
<span>
<a>
</li>
<li>
<a>
<span>
<a>
</li>
...
</ul>
-
-
...
我认为实现这一点的XPath应该是//ul/li/a[position()=1]
说明:
我之所以将其全部拼写为//ul/li/a
,是因为当您使用xpath时,如果出现错误,堆栈跟踪将准确显示定位器指向的内容,并且不那么模糊。但是,如果你不在乎的话,你显然可以用速记://a
使用position子句,您可以执行=1
或>1
等操作。我会选择使用[position()=1]
而不是使用[1]
,因为Xpath不使用基于0的数组,这可能会让其他查看定位器的人感到困惑。我的意思是position=0
,从逻辑上讲,意味着空值,对吗
我用
开始我的定位器,因为就我个人而言,有时我喜欢将定位器组合在一起。您实际上不需要以点字符开头,但由于我在本例中使用了/
通配符,因此它实际上与没有点的开头相同,但具有链接的附加功能
测试答案
@马西亚斯:你说得对,我道歉//li/a[1]不起作用,因为它不是直接的子对象(中间有一个article标记,为了简单起见,我省略了它)
然后,让我将此作为一个解决方案发布,并进行更多解释
如前所述,如果//li/a[1]
没有返回任何内容,而(//li//a)[1]
没有返回任何内容,则显示的HTML示例不能代表实际文档。那么,a
将是li
的后代,而不是它的直系子代
在这种情况下,正确的XPath表达式是
//li//a[1]
但仅当嵌套级别不同时才使用它,即如果在li
和a
之间可能嵌套其他元素:
<li>
<article>
<other>
<a/>
这避免了计算成本高于/
的/
轴
最后,如果您知道您感兴趣的a
元素始终是li
元素的孙子,并且如果它们之间始终是文章
元素,请使用
//li/article/a[1]
当我将表达式更正为//li/article/a[1]”时,我得到第一个li的第一个a`
//li/article/a[1]
如果有多个a
元素是article
的子元素和li
的孙子元素,则返回多个结果。如果这只返回一个结果
- 在只需要一个结果的上下文中调用此XPath表达式,例如,如果在编程语言或应用程序中使用XPath库
- 输入文档的结构更加复杂
请显示您尝试过但未给出正确结果的XPath表达式。@Mathias我尝试过://li//code>-它返回所有
节点,(//li//a)[1]
-它返回第一个“”节点的第一个
,(//li)[1]//a
-返回第一个
的所有
节点,以及//li/a[1]
-没有返回任何内容。如果//li/a[1]
没有返回任何内容,而(//li//a)[1]
没有返回任何内容,则显示的HTML示例不能代表实际文档。那么,a
将是li
的后代,而不是它的直系子代。请出示一个更完整的样品。@Mathias:你说得对,我道歉//li/a[1]
不起作用,因为它不是直接的子对象(中间有一个文章
标记,为了简单起见,我省略了该标记)。当我将表达式更正为//li/article/a[1]
时,对于第一个li
,我得到了第一个a
。这会让事情变得更清楚吗?不,在这种情况下,不需要用
启动XPath表达式,如果上下文节点不是文档节点,它甚至是有害的(../ul/li/a)[position()=1]
返回0或1个结果节点,在我看来,这显然不是OP想要的。他们想选择每个li
的第一个a
元素,这是一个以上的结果。@MathiasMüller Yep,你完全正确。我的定位器错了。我想我已经修好了。谢谢你编辑了你的答案,但我仍然不明白为什么以
开头的表达式会有助于链接。你能举例说明一下吗?以/
开头的路径表达式可以很容易地附加到另一个路径表达式。在使用Selenium的上下文中进行链接。
//li/article/a[1]