Problème lors de l'analyse des enfants d'un nœud avec HtmlAgilityPack

c# html-agility-pack html-parsing xpath

Question

Je ne parviens pas à analyser les enfants de la balise input d'un formulaire en HTML. Je peux les analyser à partir de la racine en utilisant // input [@type] mais pas en tant qu'enfants d'un nœud spécifique.

Voici un code qui illustre le problème:

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");
        }
    }

Quelle est la sortie est:

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

Je m'attendrais à ce que Form1 et Form2 aient tous deux des enfants et que l'entrée [@type] puisse trouver 2 nœuds pour form1 et 1 pour form2

Existe-t-il un paramètre de configuration ou une méthode que je n'utilise pas que je devrais être? Des idées?

Merci,

Steve

Réponse acceptée

Eh bien, j'ai abandonné HtmlAgilityPack pour le moment. On dirait qu'il reste encore beaucoup de travail à faire dans cette bibliothèque pour que tout fonctionne. Pour résoudre ce problème, j'ai déplacé le code pour utiliser la bibliothèque SGMLReader à partir d'ici: http://developer.mindtouch.com/SgmlReader

En utilisant cette bibliothèque, tous mes tests unitaires réussissent correctement et l'exemple de code fonctionne comme prévu.


Réponse populaire

Découvrez ce fil de discussion sur le site HtmlAgilityPack - http://htmlagilitypack.codeplex.com/workitem/21782

Voici ce qu'ils disent:

Ce n'est pas un bug, mais une fonctionnalité et est configurable. FORM est traité comme ceci parce que beaucoup de pages HTML avaient des formulaires qui se chevauchaient, car c'était en fait une fonctionnalité (puissante) du HTML original. Maintenant que XML et XHTML existent, tout le monde suppose que le chevauchement est une erreur, mais ce n’est pas le cas (en HTML 3.2). Vérifiez le fichier HtmlNode.cs et modifiez la collection ElementsFlags (ou faites-le au moment de l'exécution si vous préférez)

Pour modifier le fichier HtmlNode.cs, commentez la ligne suivante -

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


Related

Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow