ist es möglich, das Problem in HtmlAgilityPack zu beheben, wenn es einen nicht geschlossen HTML-Tag ist?
-
20-09-2019 - |
Frage
Nun, ich habe folgendes Problem.
die html ich habe ist falsch formatiert, und ich habe Probleme mit der Auswahl Knoten mit HTML Agilität packen, wenn dies der Fall ist.
der Code ist unter:
string strHtml = @"
<html>
<div>
<p><strong>Elem_A</strong>String_A1_2 String_A1_2</p>
<p><strong>Elem_B</strong>String_B1_2 String_B1_2</p>
</div>
<div>
<p><strong>Elem_A</strong>String_A2_2 <String_A2_2> asdas</p>
<p><strong>Elem_B</strong>String_B2_2 String_B2_2</p>
</div>
</html>";
HtmlAgilityPack.HtmlDocument objHtmlDocument = new HtmlAgilityPack.HtmlDocument();
objHtmlDocument.LoadHtml(strHtml);
HtmlAgilityPack.HtmlNodeCollection colnodePs = objHtmlDocument.DocumentNode.SelectNodes("//p");
List<string> lststrText = new List<string>();
foreach (HtmlAgilityPack.HtmlNode nodeP in colnodePs)
{
lststrText.Add(nodeP.InnerHtml);
}
das Problem ist, dass String_A2_2 in Klammern eingeschlossen ist.
so htmlagility Pack kehrt 5 Strings statt 4 im lststrText.
so ist es möglich, htmlagility Pack Rückstellelement 3, wie zu lassen
"<strong>Elem_A</strong>String_A2_2 <String_A2_2> asdas"
?
oder vielleicht kann ich tun, einige Vorverarbeitung das Element zu schließen?
der aktuelle Inhalt von lststrText ist
lststrText[0] = "<strong>Elem_A</strong>String_A1_2 String_A1_2"
lststrText[1] = "<strong>Elem_B</strong>String_B1_2 String_B1_2"
lststrText[2] = ""
lststrText[3] = ""
lststrText[4] = "<strong>Elem_B</strong>String_B2_2 String_B2_2"
Lösung
Die meisten HTML-Parser versuchen, eine Arbeits DOM zu bauen, was bedeutet, baumelnde Tags werden nicht akzeptiert. Sie werden in irgendeiner Weise umgewandelt oder geschlossen wird.
Wenn nur die Knoten der Auswahl ist wichtig für Sie, und die Geschwindigkeit und große Datenmengen kein Problem, könnte man all
-Tags mit einem regulären Ausdruck greift statt:
Regex reMatchP = new Regex(@"<(p)>.*?</\1>");
foreach (Match m in reMatchP.Matches(strHtml))
{
Console.WriteLine(m.Value);
}
Dieser reguläre Ausdruck übernimmt die
-Tags gut ausgebildet sind und geschlossen werden.
Wenn Sie dieses Regex viel in Ihrem Programm ausführen sollten Sie es erklären, wie:
static Regex reMatchP = new Regex(@"<(p)>.*?</\1>", RegexOptions.Compiled);
[Edit: Agility Pack ändern]
Wenn Sie verwenden möchten HtmlAgility packen Sie die PushNodeEnd Funktion in HtmlDocument.cs ändern können:
if (HtmlNode.IsCDataElement(CurrentNodeName()))
{
_state = ParseState.PcData;
return true;
}
// new code start
if ( !AllowedTags.Contains(_currentnode.Name) )
{
close = true;
}
// new code end
Dabei gilt AllowedTags eine Liste aller bekannten Tags wäre. B, p, br, spanne, div, etc
der Ausgang ist nicht 100%, was Sie wollen, aber vielleicht nahe genug?
<strong>Elem_A</strong>String_A1_2 String_A1_2
<strong>Elem_B</strong>String_B1_2 String_B1_2
<strong>Elem_A</strong>String_A2_2 <ignorestring_a2_2></ignorestring_a2_2> asdas
<strong>Elem_B</strong>String_B2_2 String_B2_2
Andere Tipps
könnten Sie verwenden TidyNet das zu tun pre / Post-processing Sie spielen auf. Können Sie Ihre Antwort bearbeiten, zu erklären, warum das würde nicht in Ihrem Fall anwendbar sein?