2014-09-03 3 views
1

Я разбираю HTML DOM в C# с библиотекой HTMLAgilityPack и хотел бы знать, как пересечь DOM, как только я попаду к определенному элементу.Traverse DOM с пакетом гибкости HTML

Например, когда я добираюсь до td с классом «некоторым класс», я хочу, чтобы перейти к третьему собрату td и захватить href ее вложенную anchor.

<td class="some-class">Content I care about</td> 
<td>Content I don't want</td> 
<td>Content I don't want</td> 
<td>  
    <a href="http://www.the-url-I-want.com">Some Amazing URL</a> 
</td> 

В настоящее время я совершил посадку на td Я хочу через:

foreach(HtmlNode node in doc.DocumentNode.SelectNodes("//td")) 
{ 
    HtmlAttribute nodeClass = node.Attributes["class"]; 

    if(nodeClass != null && nodeClass.Value == "some-class") 
    { 
     //Find the anchor that is 3 siblings away 
     //Do something 
    } 
} 

Кто-нибудь знает, как я хотел бы использовать HTMLAgility пакет, чтобы захватить соответствующий якорь для индивидуального td?

+0

До сих пор это работает (но чувствует себя смехотворно неуклюжее) ... 'HtmlNode siblingAnchor = node.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.FirstChild.NextSibling;' –

+0

Это на самом деле является разумным кодом для получения определенного узла-брата (если вы можете терпеть случайное «NullRefferenceException», если HTML изменяется). Я бы рекомендовал прочитать некоторые базовые учебники по XPath, чтобы иметь возможность более точно/быстрее выбирать элементы (т. Е. '' // "' искать все дерево для соответствия, и часто вы можете сузить поиск по крайней мере до определенного поддерева, вы также можете сопоставлять атрибуты напрямую с XPath). –

+0

@AlexeiLevenkov HTML должен быть статичным, и если он изменится, я смогу проверить на выходе программы. Я буду копаться в учебниках по XPath, чтобы посмотреть, как оптимизировать. Еще раз спасибо за ссылку на HTMLAgilityPack, btw :) –

ответ

3

Изучите XPath, и ваша работа может быть намного проще. Например, чтобы получить <td> элемент, имеющий атрибут класса равен «какой-то класс», мы можем использовать этот Xpath:

//td[@class='some-class'] 

И для получения третьего следующий родственный <td>:

/following-sibling::td[3] 

Таким образом, ваш цикл может быть переписано следующим образом:

var xpath = "//td[@class='some-class']/following-sibling::td[3]/a"; 
foreach(HtmlNode a in doc.DocumentNode.SelectNodes(xpath)) 
{ 
    //Do something with the anchor variable a 
} 

BTW, безопасный способ для получения значения атрибута используется GetAttributeValue() метода:

var href = a.GetAttributeValue("href", ""); 

Второй аргумент - значение по умолчанию, которое будет возвращено, если атрибут не найден.

+2

У этой проблемы будет проблема, если 'td' имеет более одного класса (' td class = "one_class two_class" '). Appart от этого, он красив в своей простоте. http://stackoverflow.com/questions/1604471/how-can-i-find-an-element-by-css-class-with-xpath обрабатывает несколько классов. –

+0

@JonP Сообщение, которое вы связали, действительно содержит полезную информацию. Мой ответ просто не пытался осветить все возможные проблемы, если он не будет четко отражен в разметке образца OP, чтобы сохранить это простое – har07

+0

. Я согласен, держите его как можно проще, как можно дольше. –

Смежные вопросы