Ich versuche, eine bestimmte HTML-Zeichenfolge zu analysieren, so dass ich eine Reihe von Zeilen, die durch <br/>
Bruchlinien getrennt sind, extrahieren kann. Das Eingabe-HTML sieht folgendermaßen aus:
<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>
Mit diesem Div in einem größeren HTML-Dokument konnte ich die HTML ChildNodes
List<HtmlNode> nodes = htmlDoc.DocumentNode
.Descendants("div")
.Where(x => x.Attributes.Contains("class") &&
x.Attributes["class"].Value.Contains("PlainText")).ToList();
Ich bin mir nicht ganz sicher, wohin ich von hier aus gehen soll, ich möchte den ganzen Text lesen, bis ich zwei Bruchlinien sehe und aufhöre?
BEARBEITEN
Ich schaute auf dem childnodes nodes
in Visual Studio Runtime - Inspektoren und bemerkte , dass es tatsächlich nicht zwei consectuive <br/>
Linien , sondern eine einzige Bruchlinie und einen #text
- Tag mit seinem innerHTML- Wesen \n
ein neuen Zeile Zeichen.
So etwas sollte funktionieren
[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";
}
Was zurückkommt
Beachten Sie, dass der Kommentar nach den beiden Brs nicht zurückgegeben wurde
BEARBEITEN:
Ich habe leere #text
Werte entfernt, da Sie, wenn Sie einen Zeilenumbruch zwischen den letzten beiden br
Tags haben, ein # #text
Tag mit Zeilenumbrüchen erhalten. Ich denke, hier liegt die Verwirrung in der Newline.
Sie können XPath //div[@class='PlainText']
, um erforderliche div-Knoten zu erhalten. Sie können auch den nächsten Geschwisterknoten überprüfen, wenn Sie untergeordnete Knoten von div nehmen:
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));
Ich verwende Inline-Lambda nicht nur zur besseren Lesbarkeit. Bedingung funktioniert wie folgt:
br
Knoten, wenn nicht - aktuelle Knoten nehmen br
Knoten, wenn nicht - aktuelle Knoten nehmen Ergebnis: