Утверждение XPath для поиска ближайшего предыдущего брата

c# html-agility-pack xpath

Вопрос

Я использую HTMLAgilityPack в приложении C # WPF для прокрутки некоторых якорных тегов на локальной 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, я хочу найти субтитры1. Аналогично для link2 и link3. Но для link4 и link5 я хочу найти субтитры2. Я использую этот оператор 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 для возвращения ближайшего родственника?

Принятый ответ

локатор для получения субтитров по тексту ссылки ('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()]

мы надеемся, что это поможет кому-то получить логику для создания локаторов


Популярные ответы

Попробуйте использовать xpath:

//a[@href='<your_input>']/preceding-sibling::tr[.//a[@class='subtitle']][1]

где <your_input> может быть link1.pdf на link5.pdf



Related

Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow