HTML Agility Pack(C#)使我的代码出错

时间:2013-05-06 18:28:29

标签: c# xhtml html-agility-pack

我目前正在用c#编写桌面应用程序,它还必须处理XHTML文档操作。为此,我使用 Html Agility Pack ,到目前为止似乎没问题。仔细检查Html Agility Pack的输出后,我发现代码不再格式化为xhtml。

删除自关闭标签(斜杠)并覆盖其他专有代码元素......

例如。 输入HTML代码

<input autocapitalize="off" id="username" name="username" placeholder="Benutzername" type="text" value="$(username)" />

例如。 输出HTML代码

<input autocapitalize="off" id="username" name="username" placeholder="Benutzername" type="text" value="$(username)">

(删除了斜杠......)

另一个例子是专有代码元素(用于Mikrotik热点设备):

例如输入html代码

<form action="$(link-login-only)" method="post" name="login" $(if chap-id) onSubmit="return doLogin()"$(endif)>

$(if chap-id)$(endif)$(link-login-only)部分是从Mikrotik设备解释的自定义代码片段。

例如。 在Html Agility Pack之后输出html代码(将其转换为不可用的代码)

<form action="$(link-login-only)" method="post" name="login" $(if="" chap-id)="" onsubmit="return doLogin()" $(endif)="">

有人知道如何“指示”Html Agility Pack输出结构良好的XHTML并忽略“自定义代码”片段(可能是通过Regex)吗?

提前致谢! : - )

3 个答案:

答案 0 :(得分:3)

在您的第一个示例中,HTML Agility Pack实际上正在修复您的标记。输入元素是void element。由于内部没有上下文,因此不需要结束标记。

HTML Agility Pack用于解析有效的HTML标记,而不是嵌入自定义代码的标记。在您的第一个示例中,自定义标记在引号内,因此不是问题。在第二个示例中,变量在引号之外。

HTML Agility Pack尝试将它们解析为元素的常规(但格式不正确)属性。没有办法解决这个问题。如果需要支持标记内的自定义代码,则必须找到另一种解析标记的方法。

答案 1 :(得分:2)

Necromancing。
问题1是因为您可能没有指定OptionOutputAsXml = true,这意味着HtmlAgilityPack输出HTML而不是XHTML。

实际上,这样做很聪明,因为它会减小文件大小 如果您需要XHTML,您需要专门指示HtmlAgilityPack输出XHTML(XML),而不是HTML(SGML)。

SGML允许标签没有结束标签(/>),而XML则不允许 解决这个问题:

public static void BeautifyHtml()
{
    string input = "<html><body><p>This is some test test<br ><ul><li>item 1<li>item2<</ul></body>";

    HtmlAgilityPack.HtmlDocument test = new HtmlAgilityPack.HtmlDocument();
    test.LoadHtml(input);
    test.OptionOutputAsXml = true;
    test.OptionCheckSyntax = true;
    test.OptionFixNestedTags = true;


    System.Text.StringBuilder sb = new System.Text.StringBuilder();
    using (System.IO.TextWriter stringWriter = new System.IO.StringWriter(sb))
    {
        test.Save(stringWriter);
    }

    string beautified = sb.ToString();
    System.Console.WriteLine(beautified);
}

答案 2 :(得分:0)

另一种选择是CsQuery,至少对于你在这里遇到的简单情况,它只会将你的预处理器标签单独处理,就像将它们视为无价值的属性一样。也就是说,HAP似乎将没有值的任何属性someattribute转换为someattribute=""。 CsQuery不会这样做。

然而@Justin Niessner关于你的标记的观察对于任何不是专门用于解析你在那里的模板代码的解析器都是正确的。仅仅因为这个例子通过CsQuery实现,并不能保证某些其他格式不会导致某些不是有效的属性名称,或者如果无效,至少可以被HTML5解析器接受。

如果您需要以HTML格式操作某些内容,请在模板化后执行此操作。如果你需要在模板引擎之前操作它,那么你就是陷阱22,因为它还不是HTML。或者,您可以使用模板系统为其关键字使用有效的HTML标记(例如:Knockout)。