Analizza HTML dalle linee di discontinuità usando HTML AgilityPack

c# html-agility-pack parsing

Domanda

Sto cercando di analizzare una stringa HTML specifica in modo da poter estrarre un insieme di righe spezzate da <br/> break lines. L'HTML di input è simile al seguente:

<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>

Con questo div in un documento html più grande, sono stato in grado di ottenere i HTML ChildNodes

<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>

Non sono del tutto sicuro di dove andare da qui, mi piacerebbe leggere tutto il testo fino a quando non vedo due linee di frattura e mi fermo?

MODIFICARE

Ho guardato le childNodes nodes in Visual Studio runtime ispettore e notato che in realtà non è due consectuive <br/> linee, ma una sola linea di rottura ed una #text tag con il suo InnerHtml essere \n un carattere di nuova riga.

inserisci la descrizione dell'immagine qui

Risposta accettata

Qualcosa del genere dovrebbe funzionare

[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";
}

Che ritorna

inserisci la descrizione dell'immagine qui

Nota come non ha restituito il commento dopo le due br

MODIFICARE:

Ho rimosso i valori #text vuoti poiché quando si ha una nuova riga tra gli ultimi due tag br si ottiene effettivamente un tag #text con #text . Penso che sia qui che risiede la confusione di newline.


Risposta popolare

Puoi usare XPath //div[@class='PlainText'] per ottenere i div nodi richiesti. Inoltre, puoi controllare il prossimo nodo fratello durante l'acquisizione di nodi figlio da 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));

Non uso lambda in linea solo per la leggibilità. La condizione funziona così:

  • Controlla se il nodo successivo è nullo, se è nullo, quindi prendi il nodo corrente
  • Controlla se il nodo successivo è br nodo, in caso contrario - prendi il nodo corrente
  • Controlla se il nodo corrente è br nodo, in caso contrario - prendi il nodo corrente
  • Altrimenti smettere di prendere i nodi figli

Risultato:

inserisci la descrizione dell'immagine qui




Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché