我在C#WPF应用程序中使用HTMLAgilityPack来遍历本地HTML页面中的一些锚标记并提取href属性。这很好用,但我需要在HTML文档中找到锚点所在的标题(这也是一个锚标记)。这应该很容易与XPath一起使用,但我似乎无法获得适用于所有场景的语句。
这是我的HTML示例(我无法控制):
<html>
<body>
<table>
<tr>
<td><div><a href="#maintitle" class="title">maintitle</a></div></td>
</tr>
<tr>
<td><div><a href="#subtitle1" class="subtitle">subtitle1</a></div></td>
</tr>
<tr>
<td><div><a href="link1.pdf">link1</a></div></td>
</tr>
<tr>
<td><div><a href="link2.pdf">link2</a></div></td>
</tr>
<tr>
<td><div><a href="link3.pdf">link3</a></div></td>
</tr>
<tr>
<td><div><a href="#subtitle2" class="subtitle">subtitle2</a></div></td>
</tr>
<tr>
<td><div><a href="link4.pdf">link4</a></div></td>
</tr>
<tr>
<td><div><a href="link5.pdf">link5</a></div></td>
</tr>
</table>
</body>
</html>
找到link1后,我想找到subtitle1。同样适用于link2和link3。但对于link4和link5,我想找到subtitle2。我正在使用这个XPath语句(第一部分就是为了模拟一个锚标签的选择,我已经在线上使用了XPath评估器https://www.freeformatter.com/xpath-tester.html):
//a[@href='link4.pdf']/ancestor::tr/preceding-sibling::tr//a[@class='subtitle']
这适用于link1到link3,但对于link4和link5,它返回subtitle1和subtitle2。将[1]
添加到preceding-sibling::t
会为link4修复它,但会将其分解为link2,link3和link5:
//a[@href='link4.pdf']/ancestor::tr/preceding-sibling::tr[1]//a[@class='subtitle']
我还尝试将last()
添加到preceding-sibling::t
,但这导致没有找到任何链接:
//a[@href='link4.pdf']/ancestor::tr/preceding-sibling::tr[last()]//a[@class='subtitle']
我确信这是一个简单的解决方案,但我绝不能胜任XPath,所以我很难挣扎。如何获取原始XPath语句以返回最近的兄弟姐妹?
答案 0 :(得分:3)
通过链接文字获取字幕的定位器(&#39; link4&#39;)
(//a[text()='link5']/preceding::tr[.//a[@class='subtitle']])[last()]
逻辑:
//a[text()='link4']
- 按链接文字获取元素
//a[text()='link4']/preceding::tr
- 搜索所有tr父母
[.//a[@class='subtitle']]
- 获取包含标记a
的第一个父级 课程&#39;subtitle
&#39;获取包含标记
(someLocator)[last()]
- 获取最后一个匹配定位符的元素,在我们的示例中 - 使用类&#39;a
&#39;subtitle
的最后一个父元素
另一种选择 - 最初搜索tr
而不是a
元素
(//tr[.//a[text()='link5']]/preceding-sibling::tr//a[contains(@class,'subtitle')])[last()]
希望它能帮助任何人获得逻辑构建定位器
答案 1 :(得分:0)
尝试使用xpath:
//a[@href='<your_input>']/preceding-sibling::tr[.//a[@class='subtitle']][1]
其中<your_input>
可以是link1.pdf
到link5.pdf