Problem beim Parsen von Kindern eines Knotens mit HtmlAgilityPack

c# html-agility-pack html-parsing xpath

Frage

Ich habe ein Problem beim Parsen der Eingabe-Tag-Kinder eines Formulars in HTML. Ich kann sie mit // input [@type] von der Wurzel aus analysieren, aber nicht als Kind eines bestimmten Knotens.

Hier ist ein Code, der das Problem veranschaulicht:

private const string HTML_CONTENT =
        "<html>" +
        "<head>" +
        "<title>Test Page</title>" +
        "<link href='site.css' rel='stylesheet' type='text/css' />" +
        "</head>" +
        "<body>" +
        "<form id='form1' method='post' action='http://www.someplace.com/input'>" +
        "<input type='hidden' name='id' value='test' />" +
        "<input type='text' name='something' value='something' />" +
        "</form>" +
        "<a href='http://www.someplace.com'>Someplace</a>" +
        "<a href='http://www.someplace.com/other'><img src='http://www.someplace.com/image.jpg' alt='Someplace Image'/></a>" +
        "<form id='form2' method='post' action='/something/to/do'>" +
        "<input type='text' name='secondForm' value='this should be in the second form' />" +
        "</form>" +
        "</body>" +
        "</html>";

public void Parser_Test()
    {
        var htmlDoc = new HtmlDocument
        {
            OptionFixNestedTags = true,
            OptionUseIdAttribute = true,
            OptionAutoCloseOnEnd = true,
            OptionAddDebuggingAttributes = true
        };

        byte[] byteArray = Encoding.UTF8.GetBytes(HTML_CONTENT);
        var stream = new MemoryStream(byteArray);
        htmlDoc.Load(stream, Encoding.UTF8, true);
        var nodeCollection = htmlDoc.DocumentNode.SelectNodes("//form");
        if (nodeCollection != null && nodeCollection.Count > 0)
        {
            foreach (var form in nodeCollection)
            {
                var id = form.GetAttributeValue("id", string.Empty);
                if (!form.HasChildNodes)
                    Debug.WriteLine(string.Format("Form {0} has no children", id ) );

                var childCollection = form.SelectNodes("input[@type]");
                if (childCollection != null && childCollection.Count > 0)
                {
                    Debug.WriteLine("Got some child nodes");
                }
                else
                {
                    Debug.WriteLine("Unable to find input nodes as children of Form");
                }
            }
            var inputNodes = htmlDoc.DocumentNode.SelectNodes("//input");
            if (inputNodes != null && inputNodes.Count > 0)
            {
                Debug.WriteLine(string.Format("Found {0} input nodes when parsed from root", inputNodes.Count ) );
            }
        }
        else
        {
            Debug.WriteLine("Found no forms");
        }
    }

Was ausgegeben wird, ist:

Form form1 has no children
Unable to find input nodes as children of Form
Form form2 has no children
Unable to find input nodes as children of Form
Found 3 input nodes when parsed from root

Was ich erwarten würde ist, dass Form1 und Form2 beide Kinder haben würden und dass Eingabe [@type] 2 Knoten für Form1 und 1 für Form2 finden könnte

Gibt es eine bestimmte Konfigurationseinstellung oder Methode, die ich nicht verwende, die ich sein sollte? Irgendwelche Ideen?

Vielen Dank,

Steve

Akzeptierte Antwort

Nun, ich habe HtmlAgilityPack für jetzt aufgegeben. Es scheint, als ob noch mehr Arbeit in dieser Bibliothek zu erledigen ist, um alles zum Laufen zu bringen. Um dieses Problem zu lösen, habe ich den Code verschoben, um die SGMLReader-Bibliothek von hier zu verwenden: http://developer.mindtouch.com/SgmlReader

Mit dieser Bibliothek werden alle Komponententests ordnungsgemäß ausgeführt und der Beispielcode funktioniert wie erwartet.


Beliebte Antwort

Sehen Sie sich diesen Diskussions-Thread auf der HtmlAgilityPack-Site an - http://htmlagilitypack.codeplex.com/workitem/21782

Das sagen sie:

Dies ist kein Fehler, sondern eine Funktion und ist konfigurierbar. FORM wird so behandelt, weil viele HTML-Seiten überlappende Formulare enthielten, da dies tatsächlich eine (leistungsstarke) Funktion des ursprünglichen HTML war. Nun, da XML und XHTML existieren, nimmt jeder an, dass Überlappung ein Fehler ist, aber es ist nicht (in HTML 3.2). Überprüfen Sie die Datei HtmlNode.cs, und ändern Sie die ElementsFlags-Auflistung (oder tun Sie es zur Laufzeit, wenn Sie dies bevorzugen)

Um die Datei HtmlNode.cs zu ändern, geben Sie folgende Zeile aus -

ElementsFlags.Add("form", HtmlElementFlag.CanOverlap | HtmlElementFlag.Empty);


Related

Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow