HtmlAgilityPack sélectionne les données du sous-noeud

c# html html-agility-pack linq parsing

Question

J'ai le code HTML suivant que je voudrais analyser:

<h3 class='bar'>
  <a href='http://anysite.com/index.php?showuser=7195' title='Profile view'>THIS_IS_USERNAME</a>
  &nbsp;
  <a href='http://anysite.com/index.php?showuser=7195&amp;f=' class='__user __id7195' title='Profile view'>
      <img src='http://anysite.com/public/style_images/car/user_popup.png' alt='' />
   </a>
</h3>

Ce dont j'ai besoin ici est de sélectionner le nom d'utilisateur ("THIS_IS_USERNAME") et le lien vers le profil (" http://anysite.com/index.php?showuser=7195 ").

Je peux sélectionner le nœud h3 supérieur en utilisant le code suivant:

List<HtmlNode> resultSearch = HTMLPage.DocumentNode.Descendants()
                .Where(
                         x => x.Name.Equals("h3")
                         && x.Attributes["class"] != null
                         && x.Attributes["class"].Value.Equals("bar")                         
                      )
                .ToList();

Mais comment puis-je obtenir le noeud "h3" lui-même, mais "un" à l'intérieur "h3" avec ce lien d'attributs contenant le nom d'utilisateur et le lien vers le profil dont j'ai besoin?

Réponse acceptée

Vous pouvez interroger directement le nœud de lien, il est assez distinctif avec l'attribut Title.

Dans ce cas, utiliser un XPath est probablement plus simple car il gère toutes les vérifications nulles intermédiaires et est tout aussi sûr pour le type, car votre requête Linq aura beaucoup de chaînes constantes:

var node = HTMLPage.DocumentNode.SelectSingleNode("//hr[@class='Bar']/a[@title='Profile View' and @href");
if (node != null)
{
    string link = node.Attributes["href"].Value;
    string username = node.InnerText;
}

Vous pouvez écrire un code similaire en utilisant la syntaxe Linq. Celui-ci commence par rechercher la balise link, puis effectue un retour arrière pour rechercher un parent h3. De cette façon, vous n'avez pas à vérifier les valeurs nulles intermédiaires;):

var node = HtmlPage.DocumentNode.Descendants("a")
    .Where(a =>
        a.Ascendants("h3")
            .Any(h3 =>
                h3.Attributes["class"] != null 
                && a.Attributes["class"].Value == "bar"
            )
    )
    .Where(a => 
        a.Attributes["title"] != null 
        && a.Attributes["title"].Value == "Profile View"
        && a.Attributes["href"] != null
    )
    .FirstOrDefault();

if (node != null)
{
    string link = node.Attributes["href"].value;
    string username = node.InnerText;
}

Ou vous pouvez utiliser la position du premier <a> enfant de "bar":

// the call to First() will throw an exception if the h3 isn't found.
// returning an empty HtmlNode will allow you to ignore that

var node = (HtmlPage.DocumentNode.Descendants("h3")
    .FirstOrDefault( h => 
            h3.Attributes["class"] != null 
            && a.Attributes["class"].Value == "bar")
    ) ?? HtmlPage.CreateElement("h3")) 
    .Elements("a").FirstOrDefault();

if (node != null)
{
    string link = node.Attributes["href"].value;
    string username = node.InnerText;
}



Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi