【问题标题】:Best way to "fix" malformed html for use in an xsl transform在 xsl 转换中“修复”格式错误的 html 的最佳方法
【发布时间】:2013-09-18 12:47:57
【问题描述】:

我有一个输入 xml 文档,其中包含格式错误的 html,该 html 已经过 xml 编码。 即 xml 文档本身在技术上是有效的。

现在我正在对输出格式正确的 xhtml5 但包含格式错误的 html 的 xml 应用 xsl 转换。

不良 html 示例:

  • html 片段中的 html、head 和 body 标签。
  • 字体标签
  • 引号不匹配
  • 未封闭的标签
  • 没有匹配打开的额外关闭标签
  • 以错误的顺序关闭标签(例如<b><u>text</b></u>

现在在我的情况下,我实际上并不关心 html 的格式是否错误 - 我只关心 my 结束标签是否与我的开始标签匹配,无论中间发生什么。

所以我的问题是 - 最好的方法是什么

  1. 充分清理 html,使其不会影响其他标签(最好从转换本身内部)
  2. 或以某种方式标记一个closetag,以便与html5 兼容的浏览器将其识别为匹配特定的打开标记,而不管其间可能存在任何讨厌的标记。

对于 2。我完全没有想法。对于 1. 我有几个想法,例如调用 tidy 之类的外部工具或使用 .NET sgml 解析器

.NET xsl 脚本 (msxsl:script) 是可以接受的,如果不需要的话。

示例来源:

<xml>
  &lt;b&gt;&lt;u&gt;bad html&lt;/b&gt;&lt;/u&gt;
<xml>

示例输出:

<div id="MyDiv">
  <b><u>bad html</b></u>
</div> <!-- this /div absolutly must match the opening div regardless of what might be in the bad html -->

还有哪些其他可用的方法?

仅限 C#、VS2012、xslt 1.0

【问题讨论】:

  • 您的“格式错误”的 html 是否真的在 CDATA 标记中?在您的问题中包含一小部分 XML 示例以及您期望输出的示例可能会有所帮助。谢谢!
  • 它是 xml 编码的 - 所以 &amp;lt;html&amp;gt;

标签: c# .net html xslt xslt-1.0


【解决方案1】:

是否可以使用第三方库? HTML Agility Pack(在 NuGet 上可用)可能是解决无效 HTML 的一部分,而且它(根据网站)还支持 XSLT。

【讨论】:

  • 我对 HTML Agility Pack 的个人经验是,它在有效的 HTML 上工作得相当好,但如果 HTML 格式不正确,它很快就会放弃。我们尝试使用它将用户粘贴到我们网站的 HTML 转换为 Markdown,但它一直中断。
【解决方案2】:

我选择使用 sgml 解析库并转换为有效的 xml。

我去了 Mind Touch 的图书馆:https://github.com/MindTouch/SGMLReader

一旦编译并添加到 GAC,我就可以使用这个 xsl:

<msxsl:script language="C#" implements-prefix="myns">
  <msxsl:assembly name="SgmlReaderDll, Version=1.8.11.0, Culture=neutral, PublicKeyToken=46b2db9ca481831b"/>
    <![CDATA[
 public XPathNodeIterator SGMLStringToXml(string strSGML)
 {
 Sgml.SgmlReader sgmlReader = new Sgml.SgmlReader();
 sgmlReader.DocType = "HTML";
 sgmlReader.WhitespaceHandling = WhitespaceHandling.All;
 sgmlReader.CaseFolding = Sgml.CaseFolding.ToLower;
 sgmlReader.InputStream = new System.IO.StringReader(strSGML);

 // create document
 XmlDocument doc = new XmlDocument();
 doc.PreserveWhitespace = true;
 doc.XmlResolver = null;
 doc.Load(sgmlReader);
 return doc.CreateNavigator().Select("/*");
 }

 public string CurDir()
 {
 return (new System.IO.DirectoryInfo(".")).FullName;
 }
  ]]>

</msxsl:script>
<xsl:template match="node()" mode="PreventSelfClosingTags">
  <xsl:copy>
    <xsl:apply-templates select="@* | node()"/>
    <xsl:text> </xsl:text>
  </xsl:copy>
</xsl:template>
<xsl:template match="@*" mode="PreventSelfClosingTags">
  <xsl:copy>
    <xsl:apply-templates select="@* | node()"/>
  </xsl:copy>
</xsl:template>

并像这样使用它:

<xsl:apply-templates select="myns:SGMLStringToXml(.)/body/*" mode="PreventSelfClosingTags"/>

注意您必须使用 XslCompiledTransform 实例手动运行转换。 asp:xml 控件不喜欢 DLL 引用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多