XPath / HtmlAgilityPack: как найти элемент (a) с определенным значением для атрибута (href) и найти соседние столбцы таблицы?

c# html html-agility-pack visual-studio xpath

Вопрос

Я довольно отчаянный, потому что не могу понять, как добиться того, что я сказал в вопросе. Я уже читал множество подобных примеров, но не нашел того, что работает в точной ситуации. Итак, допустим, у меня есть следующий код:

<table><tr>
<td><a href="url-a">text A</a></td><td><a>id A</a></td><td><a>img A</a></td>
<td><a href="url-b">text B</a></td><td><a>id B</a></td><td><a>img B</a></td>
<td><a href="url-c">text C</a></td><td><a>id C</a></td><td><a>img C</a></td>
</tr></table>

Теперь у меня уже есть часть url-a. Я в основном хочу знать, как я могу получить id A и img A. Я пытаюсь «найти» строку с XPath, но я не могу найти способ заставить ее работать. Кроме того, возможно, что информация вообще отсутствует. Это моя последняя попытка (серьезно, я возился с этим уже более 3 часов, пытаясь разными способами):

if (htmlDoc.DocumentNode.SelectSingleNode(@"/a[contains(@href, 'part-url-a')]") != null)
    string ida = htmlDoc.DocumentNode.SelectSingleNode(@"/a[contains(@href, 'part-url-a')]/following-sibling::a").InnerText;

Ну, это, очевидно, неправильно, так что я был бы очень доволен, если бы кто-то мог помочь мне здесь. Также я был бы признателен, если бы кто-нибудь мог указать мне на какой-то Веб-сайт, в котором подробно объясняются XPath и обозначения / синтаксис с примерами, подобными этому. Книги также приветствуются.

PS: Я знаю, что могу достичь своей цели без XPath вообще с Regex или просто с StreamReader на C # и проверять, содержит ли каждая строка то, что мне нужно, но a) она слишком хрупка для моих нужд, потому что код может иметь резкие разрывы строк и б) Я действительно хочу остаться неизменным, полностью придерживаясь XPath за все, что я делаю в этом проекте.

Заранее спасибо за вашу помощь!

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

Используйте следующие выражения XPath :

   /*/tr/td[a[@href='url-a']]
                /following-sibling::td[1]
                     /a/text()

При оценке по предоставленному (искаженному, но скорректированному) XML-документу :

<table><tr>
<td><a href="url-a">text A</a></td><td><a>id A</a></td><td><a>img A</a></td>
<td><a href="url-b">text B</a></td><td><a>id B</a></td><td><a>img B</a></td>
<td><a href="url-c">text C</a></td><td><a>id C</a></td><td><a>img C</a></td>
</tr></table>

выбран желаемый текстовый узел :

id A

Аналогично, это выражение XPath :

   /*/tr/td[a[@href='url-a']]
                /following-sibling::td[2]
                     /a/text()

при оценке по тому же XML-документу (см. выше), выбирается другой желаемый текстовый узел :

img A

Проверка на основе XSLT :

Когда это преобразование применяется к XML-документу (см. Выше):

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="/">
  <xsl:copy-of select=
   "/*/tr/td[a[@href='url-a']]
                /following-sibling::td[1]
                     /a/text()"/>

  <xsl:text>&#10;</xsl:text>
  <xsl:copy-of select=
   "/*/tr/td[a[@href='url-a']]
                /following-sibling::td[2]
                     /a/text()"/>
 </xsl:template>
</xsl:stylesheet>

Полученные результаты :

id A
img A

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

У вас есть серьезно разбитый HTML-код с отключением закрытия td тегов. Исправьте их, пожалуйста. Это просто уродливое изображение этой разметки.

Это, как мы надеемся, Html Agility Pack может обрабатывать любое дерьмо, которое вы бросаете на него, так вот как действовать и анализировать мусор, который у вас есть, и находить значения id и img учетом href :

class Program
{
    static void Main()
    {
        var doc = new HtmlDocument();
        doc.Load("test.html");
        var anchor = doc.DocumentNode.SelectSingleNode("//a[contains(@href, 'url-a')]");
        if (anchor != null)
        {
            var id = anchor.ParentNode.SelectSingleNode("following-sibling::td/a");
            if (id != null)
            {
                Console.WriteLine(id.InnerHtml);
                var img = id.ParentNode.SelectSingleNode("following-sibling::td/a");
                if (img != null)
                {
                    Console.WriteLine(img.InnerHtml);
                }
            }
        }
    }
}


Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему
Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему