Nun, ich habe das folgende Problem.
der html, den ich habe, ist falsch und ich habe Probleme mit der Auswahl von Knoten mit html agility pack, wenn dies der Fall ist.
Der Code ist unten:
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.
Daher gibt htmlagility pack 5 Strings statt 4 im lststrText zurück.
also ist es möglich, htmlagility pack return element 3 als "<strong>Elem_A</strong>String_A2_2 <String_A2_2> asdas"
?
oder kann ich etwas Vorverarbeitung machen, um 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"
Die meisten HTML-Parser versuchen, ein funktionierendes DOM zu erstellen, was bedeutet, dass Dangling-Tags nicht akzeptiert werden. Sie werden konvertiert oder in irgendeiner Weise geschlossen.
Wenn nur die Auswahl der Knoten für Sie wichtig ist und Geschwindigkeit und große Datenmengen kein Problem darstellen, können Sie stattdessen alle Ihre <p> -Tags mit einem regulären Ausdruck erfassen:
Regex reMatchP = new Regex(@"<(p)>.*?</\1>");
foreach (Match m in reMatchP.Matches(strHtml))
{
Console.WriteLine(m.Value);
}
Dieser reguläre Ausdruck geht davon aus, dass die Tags <p> korrekt formatiert und geschlossen sind.
Wenn Sie diesen Regex in Ihrem Programm häufig ausführen möchten, sollten Sie Folgendes angeben:
static Regex reMatchP = new Regex(@"<(p)>.*?</\1>", RegexOptions.Compiled);
[Bearbeiten: Agility Pack ändern]
Wenn Sie das HtmlAgility-Paket verwenden möchten, können Sie die PushNodeEnd-Funktion in HtmlDocument.cs ändern:
if (HtmlNode.IsCDataElement(CurrentNodeName()))
{
_state = ParseState.PcData;
return true;
}
// new code start
if ( !AllowedTags.Contains(_currentnode.Name) )
{
close = true;
}
// new code end
wo AllowedTags eine Liste aller bekannten Tags wäre: b, p, br, span, div usw.
Die Ausgabe ist nicht 100% was du willst, 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
Sie könnten TidyNet für die Vor- / Nachbearbeitung verwenden, auf die Sie verweisen. Können Sie Ihre Antwort bearbeiten, um zu erklären, warum das in Ihrem Fall nicht möglich wäre?