HTMl Agility Pack-Fehler beim Parsen und Zurückgeben von XElement

.net-3.5 c# html-agility-pack html-parsing

Frage

Ich kann das Dokument analysieren und eine Ausgabe erzeugen, aber die Ausgabe kann nicht in ein XElement geparst werden, weil ein ap-Tag alles andere innerhalb der Zeichenkette korrekt analysiert.

Meine Eingabe:

var input = "<p> Not sure why is is null for some wierd reason!<br><br>I have implemented the auto save feature, but does it really work after 100s?<br></p> <p> <i>Autosave?? </i> </p> <p>we are talking...</p><p></p><hr><p><br class=\"GENTICS_ephemera\"></p>";

Mein Code:

public static XElement CleanupHtml(string input)
    {  


    HtmlAgilityPack.HtmlDocument htmlDoc = new HtmlAgilityPack.HtmlDocument();

    htmlDoc.OptionOutputAsXml = true;
    //htmlDoc.OptionWriteEmptyNodes = true;             
    //htmlDoc.OptionAutoCloseOnEnd = true;
    htmlDoc.OptionFixNestedTags = true;

    htmlDoc.LoadHtml(input);

    // ParseErrors is an ArrayList containing any errors from the Load statement
    if (htmlDoc.ParseErrors != null && htmlDoc.ParseErrors.Count() > 0)
    {

    }
    else
    {

        if (htmlDoc.DocumentNode != null)
        {
            var ndoc = new HtmlDocument(); // HTML doc instance
            HtmlNode p = ndoc.CreateElement("body");  

            p.InnerHtml = htmlDoc.DocumentNode.InnerHtml;
            var result = p.OuterHtml.Replace("<br>", "<br/>");
            result = result.Replace("<br class=\"special_class\">", "<br/>");
            result = result.Replace("<hr>", "<hr/>");
            return XElement.Parse(result, LoadOptions.PreserveWhitespace);
        }
    }
    return new XElement("body");

}

Meine Ausgabe:

<body>
   <p> Not sure why is is null for some wierd reason chappy!
   <br/>
   <br/>I have implemented the auto save feature, but does it really work after 100s?
   <br/>
   </p> 
   <p> 
   <i>Autosave?? </i> 
   </p> 
   <p>we are talking...</p>
   **<p>**
   <hr/>
   <p>
   <br/>
   </p>
</body>

Das fett gedruckte p-Tag ist dasjenige, das nicht korrekt ausgegeben wurde ... Gibt es einen Weg um das herum? Mache ich etwas falsch mit dem Code?

Akzeptierte Antwort

Was Sie versuchen, ist im Grunde eine HTML-Eingabe in eine Xml-Ausgabe zu verwandeln.

Html Agility - Pack kann das tun , wenn Sie die Verwendung OptionOutputAsXml Option, aber in diesem Fall sollten Sie die Innerhtml Eigenschaft verwenden und stattdessen lassen Sie die Html Agility - Pack für Sie den Grundstein tun, mit einem der Htmldocument des Save - Methoden.

Hier ist eine generische Funktion, um einen HTML-Text in eine XElement-Instanz zu konvertieren:

public static XElement HtmlToXElement(string html)
{
    if (html == null)
        throw new ArgumentNullException("html");

    HtmlDocument doc = new HtmlDocument();
    doc.OptionOutputAsXml = true;
    doc.LoadHtml(html);
    using (StringWriter writer = new StringWriter())
    {
        doc.Save(writer);
        using (StringReader reader = new StringReader(writer.ToString()))
        {
            return XElement.Load(reader);
        }
    }
}

Wie Sie sehen, müssen Sie nicht viel alleine arbeiten! Bitte beachten Sie, dass das Html Agility Pack automatisch einen umschließenden SPAN hinzufügt, um sicherzustellen, dass die Ausgabe ein gültiges Xml ist, da Ihr ursprünglicher Eingabetext kein Root-Element enthält.

In Ihrem Fall möchten Sie einige Tags zusätzlich verarbeiten, so, hier ist wie mit Ihrem Beispiel zu tun:

    public static XElement CleanupHtml(string input)
    {
        if (input == null)
            throw new ArgumentNullException("input");

        HtmlDocument doc = new HtmlDocument();
        doc.OptionOutputAsXml = true;
        doc.LoadHtml(input);

        // extra processing, remove some attributes using DOM
        HtmlNodeCollection coll = doc.DocumentNode.SelectNodes("//br[@class='special_class']");
        if (coll != null)
        {
            foreach (HtmlNode node in coll)
            {
                node.Attributes.Remove("class");
            }
        }

        using (StringWriter writer = new StringWriter())
        {
            doc.Save(writer);
            using (StringReader reader = new StringReader(writer.ToString()))
            {
                return XElement.Load(reader);
            }
        }
    }

Wie Sie sehen, sollten Sie keine Raw-String-Funktion verwenden, sondern stattdessen die Html Agility Pack-DOM-Funktionen (SelectNodes, Add, Remove, etc ...) verwenden.


Beliebte Antwort

Wenn Sie die Dokumentationskommentare für OptionFixNestedTags überprüfen, OptionFixNestedTags Sie Folgendes:

//     Defines if LI, TR, TH, TD tags must be partially fixed when nesting errors
//     are detected. Default is false.

Also ich glaube nicht das du mit unclosed HTML helfen p - Tags. Laut einer alten SO Frage C # Bibliothek, um HTML zu bereinigen, obwohl HTML Tidy für diesen Zweck arbeiten könnte.



Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum
Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum