Problema al analizar los hijos de un nodo con HtmlAgilityPack

c# html-agility-pack html-parsing xpath

Pregunta

Tengo un problema al analizar las etiquetas de entrada de los hijos de un formulario en html. Puedo analizarlos desde la raíz usando // input [@type] pero no como hijos de un nodo específico.

Aquí hay un código que ilustra el problema:

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

Lo que es salida es:

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

Lo que esperaría es que Form1 y Form2 tendrían hijos y que la entrada [@type] podría encontrar 2 nodos para form1 y 1 para form2

¿Hay algún ajuste de configuración o método específico que no esté usando y debería estar? ¿Algunas ideas?

Gracias,

Steve

Respuesta aceptada

Bueno, me he rendido en HtmlAgilityPack por ahora. Parece que todavía hay más trabajo por hacer en esa biblioteca para que todo funcione. Para resolver este problema, moví el código para usar la biblioteca SGMLReader desde aquí: http://developer.mindtouch.com/SgmlReader

Usando esta biblioteca, todas mis pruebas de unidad pasan correctamente y el código de ejemplo funciona como se esperaba.


Respuesta popular

Echa un vistazo a este hilo de discusión en el sitio HtmlAgilityPack - http://htmlagilitypack.codeplex.com/workitem/21782

Esto es lo que ellos dicen:

Esto no es un error, sino una característica y es configurable. FORM se trata de esta manera porque muchas páginas HTML solían tener formularios superpuestos, ya que en realidad era una característica (potente) del HTML original. Ahora que existen XML y XHTML, todos asumen que la superposición es un error, pero no lo es (en HTML 3.2). Verifique el archivo HtmlNode.cs y modifique la colección ElementsFlags (o hágalo en tiempo de ejecución si lo prefiere)

Para modificar el archivo HtmlNode.cs, comente la siguiente línea:

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


Related

Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué