HtmlAgilityPack -- <form>标签是否因某种原因自动闭合?

34

我刚刚写了这个测试来看看我是否疯了...

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using HtmlAgilityPack;

namespace HtmlAgilityPackFormBug
{
    class Program
    {
        static void Main(string[] args)
        {
            var doc = new HtmlDocument();
            doc.LoadHtml(@"
<!DOCTYPE html>
<html>
    <head>
        <title>Form Test</title>
    </head>
    <body>
        <form>
            <input type=""text"" />
            <input type=""reset"" />
            <input type=""submit"" />
        </form>
    </body>
</html>
");
            var body = doc.DocumentNode.SelectSingleNode("//body");
            foreach (var node in body.ChildNodes.Where(n => n.NodeType == HtmlNodeType.Element))
                Console.WriteLine(node.XPath);
            Console.ReadLine();
        }
    }
}

然后它输出:

/html[1]/body[1]/form[1]
/html[1]/body[1]/input[1]
/html[1]/body[1]/input[2]
/html[1]/body[1]/input[3]

但是,如果我将<form>更改为<xxx>,它会给出以下错误:

/html[1]/body[1]/xxx[1]

(正如应该的那样)。看起来这些输入元素不是在表单内,而是直接在中,就好像<form>立即关闭一样。这是怎么回事?这是个bug吗?


通过源代码挖掘,我发现:

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

它具有"empty"标志,就像META和IMG一样。为什么?表单绝对不应该是空的。


出于好奇,如果您给表单添加一个操作和方法,它是否仍然会像那样运行? - Marc Gravell
@Marc:我也有这个想法,是的,它仍然保持着那种行为。 - mpen
@Mark - 这听起来可能是一个 bug... 它显然与预期相反。 - Marc Gravell
@Marc:这太糟糕了。我的整个项目都基于它,现在我发现我不能信任它按预期执行任务。可能不得不转向SgmlReader,但我不知道那是否会更好。 - mpen
3
我完全同意。这是一个引人入胜的发现(我明天必须回来给它点赞 - 我今天的投票次数用完了)。 - Marc Gravell
由于我是原始的HAP作者,我可以解释为什么它被标记为空,请参见我的完整答案,因为评论大小有限 :) - Simon Mourier
2个回答

37

这也在此工作项中有所报告。其中包含了DarthObiwan提供的一个建议性的解决方法。

你可以在不重新编译的情况下更改它。 ElementFlags列表是HtmlNode类的静态属性。 可以通过使用以下代码来删除:

    HtmlNode.ElementsFlags.Remove("form");

在文档加载之前


谢谢Hans :) 我刚刚发现C#支持静态构造函数...那将是一个很好的地方来放置这个修复。 - mpen

25

作为原始的HAP作者,我可以解释为什么它被标记为空:

这是因为在设计HAP时,早在2000年,HTML 3.2是标准。您可能已经意识到,在HTML中,标签可以完全重叠。也就是说:<b>粗体<i>斜体和粗体</b>斜体</i> (粗体斜体和粗体斜体) 可以被所有浏览器支持(尽管它不是正式的HTML规范)。FORM标记也可以完全重叠。

由于HAP被设计为处理任何HTML内容而不是破坏当时你可能找到的大多数页面,我们决定将重叠的标签标记为空(使用ElementFlags属性),以便:

  • 您仍然可以加载它们
  • 您可以将它们保存回去而不会破坏原始HTML(如果您不需要表单内部的内容以任何编程方式)。

唯一不能做的事情是使用API、树模型或XSL等编程方式处理它们。

如今,随处可见的是XHTML/XML,这听起来很奇怪,但这就是我创建ElementFlags的原因 :)


是的...听起来很奇怪。那么问题是,您是否有计划更新HAP以使其与当前实践相适应?(感谢解释) - mpen
我不再使用HAP工作了(我有另一个类似的库,它表现更好 - 它是内部的)。我发布的最后一个版本是1.3。 HAP现在可以在codeplex上找到,由另一个人更新。这个“重叠/空标签”问题已经被提出很多次 :) 你应该在讨论/愿望中提出这个问题。 - Simon Mourier
但在OP的例子中,元素并不重叠。输入元素是封闭的。我很感激你在HAP上所做的工作。它对许多人来说是一个巨大的帮助。但希望其他作者能够修复它,或者至少有动力的人会分支它。 - Josh
3
这不是一个“修复”,因为它是按设计来的,可以通过代码进行配置,并且是开源的。这可能会导致破坏性变化。 - Simon Mourier

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接