0

我在解析 html 中表单的输入标记子项时遇到问题。我可以使用 //input[@type] 从根目录解析它们,但不能作为特定节点的子节点。

这是一些说明问题的代码:

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

输出的是:

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

我期望的是 Form1 和 Form2 都会有孩子,并且 input[@type] 将能够为 form1 找到 2 个节点,为 form2 找到 1 个节点

是否有我不应该使用的特定配置设置或方法?有任何想法吗?

谢谢,

史蒂夫

4

2 回答 2

4

在 HtmlAgilityPack 站点上查看此讨论线程 - http://htmlagilitypack.codeplex.com/workitem/21782

这就是他们所说的:

这不是错误,而是一项功能,并且是可配置的。FORM 被这样处理是因为许多 HTML 页面曾经有重叠的表单,因为这实际上是原始 HTML 的一个(强大的)功能。既然存在 XML 和 XHTML,每个人都认为重叠是一个错误,但事实并非如此(在 HTML 3.2 中)。检查 HtmlNode.cs 文件,并修改 ElementsFlags 集合(如果您愿意,也可以在运行时进行)

要修改 HtmlNode.cs 文件,请注释掉以下行 -

ElementsFlags.Add("form", HtmlElementFlag.CanOverlap | HtmlElementFlag.Empty);
于 2010-06-25T19:30:36.037 回答
2

好吧,我现在已经放弃了 HtmlAgilityPack。似乎在该库中还有更多工作要做才能让一切正常工作。为了解决这个问题,我将代码移到这里使用 SGMLReader 库:http: //developer.mindtouch.com/SgmlReader

使用这个库,我的所有单元测试都正确通过,示例代码按预期工作。

于 2010-06-23T16:34:18.363 回答