Analyser HTML par lignes de séparation à l'aide de HTML AgilityPack

c# html-agility-pack parsing

Question

Je suis en train d'analyser une chaîne HTML spécifique afin que je puisse extraire un ensemble de lignes brisées par <br/> lignes de rupture. Le HTML d'entrée ressemble à ceci:

<div class="PlainText">
  DATE: 2013-10-28 20:00:43 -0500 <br/>
  Item 1: Text1 <br/>
  Item 1: Text1 <br/>
  Item 1: Text1 <br/>
  Item 1: Text1 <br/>
  <br/> //Notice this has two break lines, i would like to stop after seeing two consecutive break lines.
</div>

Avec cette div dans un document html plus grand, j'ai pu obtenir le HTML ChildNodes

List<HtmlNode> nodes = htmlDoc.DocumentNode
                                    .Descendants("div")
                                    .Where(x => x.Attributes.Contains("class") &&
                                            x.Attributes["class"].Value.Contains("PlainText")).ToList();

Je ne sais pas trop où aller à partir de là, j'aimerais lire tout le texte jusqu'à ce que je voie deux lignes de fracture et que je m'arrête?

MODIFIER

J'ai examiné les nodes childNodes dans l'inspecteur d'exécution Visual Studio et j'ai remarqué qu'il n'y avait pas réellement deux lignes <br/> consectuives, mais une seule ligne de rupture et une balise #text dont le caractère innerHTMl était \n .

entrez la description de l'image ici

Réponse acceptée

Quelque chose comme ça devrait marcher

[Test]
public void Test()
{
    var x = ReadTillTwoBr(GetDivClass()).ToList();
}

public HtmlNode GetDivClass()
{
    var html = @"<html><div class=""PlainText"">
            DATE: 2013-10-28 20:00:43 -0500 <br/>
            Item 1: Text1 <br/>
            Item 1: Text1 <br/>
            Item 1: Text1 <br/>
            Item 1: Text1 <br/>
            <br   /> //Notice this has two break lines, i would like to stop after seeing two consecutive break lines.
            Item 3
        </div></html>";
    var doc = new HtmlDocument();
    doc.LoadHtml(html);

    return doc.DocumentNode
                .Descendants("div").First(x => x.Attributes.Contains("class") &&
                                                x.Attributes["class"].Value.Contains("PlainText"));

}

public IEnumerable<string> ReadTillTwoBr(HtmlNode node)
{
    var nonEmptyNodes =
        node.ChildNodes.Except(node.ChildNodes.Where(f => f.Name == "#text" && String.IsNullOrWhiteSpace(f.InnerHtml)))
            .ToList();

    foreach (var n in nonEmptyNodes)
    {
        if (IsBr(n) && IsBr(n.NextSibling))
        {
            yield break;
        }

        if (n.Name == "#text")
        {
            yield return n.InnerText.Trim();
        }
    }
}

public bool IsBr(HtmlNode n)
{
    return n != null && n.NodeType == HtmlNodeType.Element && n.Name == "br";
}

Qui retourne

entrez la description de l'image ici

Remarquez comment il n'a pas renvoyé le commentaire après les deux frères

MODIFIER:

J'ai supprimé les valeurs #text vides depuis que lorsque vous avez une nouvelle ligne entre les deux dernières balises br vous obtenez une balise #text avec des nouvelles lignes. Je pense que c’est là que réside la confusion.


Réponse populaire

Vous pouvez utiliser XPath //div[@class='PlainText'] pour obtenir les nœuds div requis. Vous pouvez également vérifier le prochain noeud frère lors de la prise de noeuds enfants de div:

HtmlDocument doc = new HtmlDocument();
doc.Load("index.html");
Func<HtmlNode, bool> notTwoBrakes = 
    n => (n.Name != "br" || n.NextSibling != null && n.NextSibling.Name != "br");
var nodes = doc.DocumentNode.SelectNodes("//div[@class='PlainText']")
               .Select(div => div.ChildNodes.TakeWhile(notTwoBrakes));

Je n'utilise pas inline lambda uniquement pour la lisibilité. La condition fonctionne comme ceci:

  • Vérifier si le prochain noeud est nul, s'il est nul, alors prenez le noeud actuel
  • Vérifiez si le prochain noeud est br noeud, sinon - prenez le noeud actuel
  • Vérifiez si le noeud actuel est br noeud, sinon - prenez le noeud actuel
  • Sinon, arrêtez de prendre des nœuds enfants

Résultat:

entrez la description de l'image ici



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