查找最近的前一个兄弟的 XPath 语句

Ste*_*hen 2 c# xpath html-agility-pack

我在 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>
Run Code Online (Sandbox Code Playgroud)

找到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']
Run Code Online (Sandbox Code Playgroud)

这适用于链接 1 到链接 3,但对于链接 4 和链接 5,它返回副标题 1 和副标题 2。添加[1]preceding-sibling::t修复链接4,但破坏链接2、链接3和链接5:

//a[@href='link4.pdf']/ancestor::tr/preceding-sibling::tr[1]//a[@class='subtitle']
Run Code Online (Sandbox Code Playgroud)

我也尝试添加last()preceding-sibling::t,但这导致找不到任何链接:

//a[@href='link4.pdf']/ancestor::tr/preceding-sibling::tr[last()]//a[@class='subtitle']
Run Code Online (Sandbox Code Playgroud)

我确信有一个简单的解决方案,但我绝不胜任 XPath,所以我很挣扎。如何让我的原始 XPath 语句返回最接近的兄弟?

Vit*_*yuk 6

通过链接文本获取副标题的定位器('link4')

(//a[text()='link5']/preceding::tr[.//a[@class='subtitle']])[last()]

逻辑:

//a[text()='link4'] - 通过链接文本获取元素

//a[text()='link4']/preceding::tr - 搜索所有 tr 父母

[.//a[@class='subtitle']]- 获取第一个包含a类 ' subtitle'标签的父级

(someLocator)[last()]- 获取匹配定位器的最后一个元素,在我们的例子中 - 获取最后一个包含a带有类 ' subtitle'标签的父元素

另一个选项 - 最初搜索tr而不是a元素

(//tr[.//a[text()='link5']]/preceding-sibling::tr//a[contains(@class,'subtitle')])[last()]
Run Code Online (Sandbox Code Playgroud)

希望它会帮助任何人获得逻辑 ob 构建定位器