2010-06-23 6 views
0

Je rencontre un problème lors de l'analyse de la balise input enfants d'un formulaire en html. Je peux les analyser depuis la racine en utilisant // input [@type] mais pas en tant qu'enfants d'un nœud spécifique.Problème d'analyse des enfants d'un noeud avec HtmlAgilityPack

est ici 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 sortie:

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 

Ce que j'attendre que Form1 et Form2 aurait à la fois des enfants et que l'entrée [@type ] serait capable de trouver 2 nœuds pour form1 et 1 pour form2

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

Merci,

Steve

Répondre

2

Eh bien, j'ai renoncé à HtmlAgilityPack pour l'instant. On dirait qu'il y a encore du 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 passent correctement et l'exemple de code fonctionne comme prévu.

4

Vérifiez 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é de la sorte car de nombreuses pages HTML ont des formulaires qui se chevauchent, car il s'agit en fait d'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 (dans HTML 3.2). Vérifiez le fichier HtmlNode.cs et modifier la collection ElementsFlags (ou le faire lors 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); 
+1

Pour ceux qui ne veut pas changer le code Html Agility Pack: HtmlNode.ElementsFlags.Remove ("form"); – Doug

+0

plus à ce sujet ici: http://stackoverflow.com/questions/4218847/htmlagilitypack-does-form-close-itself-for-some-reason –

+3

Je voudrais pouvoir voter plusieurs fois. Cette "caractéristique" encourage à tomber dans la fosse de l'échec. – MatthewMartin

Questions connexes