【问题标题】:HTML Agility Pack (C#) malforms my codeHTML Agility Pack (C#) 使我的代码格式错误
【发布时间】:2013-04-30 13:40:50
【问题描述】:

我目前正在用 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 并忽略“自定义代码”片段(这可能是通过正则表达式)吗?

提前致谢! :-)

【问题讨论】:

  • 为什么不使用 XML 解析器而不是 HAP(它是一个 HTML,而不是 XHTML/XML 解析器)?来自 codplex 上的项目页面:“也没有遵守 XHTML 或 XML,尽管您实际上可以使用该工具生成 XML。”
  • 你试过htmlDocument.Save(XmlWriter);
  • @I4V 我用htmlDocument.Save()-method 保存
  • @thedom 这里的关键字是XmlWriter

标签: c# xhtml html-agility-pack


【解决方案1】:

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

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

SGML 允许标签没有结束标签 (/&gt;),而 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】:

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

    但是,@Justin Niessner 对您的标记所做的观察对于任何并非专门设计用于解析其中的模板代码的解析器都是正确的。仅仅因为这个例子是通过 CsQuery 实现的,并不能保证其他格式不会导致无效的属性名称,或者如果无效,至少可以为 HTML5 解析器所接受。

    如果您需要将某些内容作为 HTML 进行操作,请在模板化后进行。如果您需要模板引擎处理它之前对其进行操作,那么您就遇到了问题22,因为它还不是HTML。或者,您也可以使用对其关键字使用有效 HTML 标记的模板系统(例如:Knockout)。

    【讨论】:

      【解决方案3】:

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

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

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

      【讨论】:

      • 知道如何做到这一点吗?我可以忍受“修复”标记,只要有任何方法可以让我的“自定义标签”保持不变......它不一定必须与 HTML Agility Pack 一起使用。
      • @Justin Niessner:“由于内部没有上下文,因此不需要结束标签。”:不正确。这取决于输出格式是 XHTML/XML 还是 HTML/SGML。在 XHTML/XML 的情况下需要它。但是问题是OP没有定义输出格式,所以HtmlAgilityPack使用了默认的(SGML)。
      • @Justin Niessner:@Stefan Steiger 所说的,加上:只是一个元素(比如div)没有实际内容,not 是否意味着结束-element 标签可以省略。在 SGML 中,只有那些声明为具有 EMPTY 内容的元素(忽略 #CONREF 属性和 WebSGML/XML)必须没有结束元素标签,例如 HTML linkhrbrimg 等元素。但是例如。 script 元素,即使与 href 属性一起使用并且没有文字脚本子内容,必须具有结束元素标记。请参阅我的 HTML 5.1 DTD sgmljs.net/docs/w3c-html51-dtd.html 以供参考
      • @imhotap - 如果您查看链接文档,我专门指的是 input 标签,它是一个 void 元素并且不需要结束标签,因为 input 标签永远不会有任何内容“里面”(与其他 void 标签一样)。
      猜你喜欢
      • 2012-10-29
      • 1970-01-01
      • 2014-05-04
      • 1970-01-01
      • 1970-01-01
      • 2017-08-27
      • 1970-01-01
      • 2020-02-16
      相关资源
      最近更新 更多