【问题标题】:How do I write unescaped XML outside of a CDATA如何在 CDATA 之外编写未转义的 XML
【发布时间】:2010-06-08 10:15:41
【问题描述】:

我正在尝试使用内容本身是 HTML 的 Stax 编写 XML 数据

如果我尝试

xtw.writeStartElement("contents");
xtw.writeCharacters("<b>here</b>");
xtw.writeEndElement();

我明白了

<contents>&lt;b&gt;here&lt;/b&gt;</contents>

然后我注意到 CDATA 方法并将我的代码更改为:

xtw.writeStartElement("contents");
xtw.writeCData("<b>here</b>");
xtw.writeEndElement();

这一次的结果是

<contents><![CDATA[<b>here</b>]]></contents>

这仍然不好。 我真正想要的是

<contents><b>here</b></contents>

那么,是否有一个 XML API/Library 允许我在不进入 CDATA 部分的情况下编写原始文本?到目前为止,我已经查看了 Stax 和 JDom,但他们似乎没有提供这个。

最后我可能会求助于好的旧 StringBuilder 但这并不优雅。

更新:

到目前为止,我大多同意这些答案。但是,我可以有一个 1MB 的 HTML 文档,而不是 &lt;b&gt;here&lt;/b&gt;,我想将它嵌入到更大的 XML 文档中。你的建议意味着我必须解析这个 HTML 文档才能理解它的结构。如果可能的话,我想避免这种情况。

答案:

这是不可能的,否则您可能会创建无效的 XML 文档。

【问题讨论】:

  • 如果这是可能的,那么您很容易编写无效的 XML 文件。并不是说大多数现实世界的 HTML(不是 XHTML)是不是有效的 XML(太多未闭合的标签和未转义的属性)。所有这些对于 HTML 来说都很好,但对于 XML 是不允许的,所以使用 CDATA 确实是唯一正确的做法,除非您的 HTML 实际上是 XHTML。
  • @Joachim。是的,就我而言,它是 XHTML。这就是为什么我知道它是有效的并且我想立即将其嵌入而不进行任何处理。

标签: java xml escaping stax


【解决方案1】:

问题在于它不是原始文本,它是一个元素,所以你应该写

xtw.writeStartElement("contents");
xtw.writeStartElement("b");
xtw.writeCData("here");
xtw.writeEndElement();
xtw.writeEndElement();

【讨论】:

  • 我认为问题在于他有一个可能包含标签的 blob。
【解决方案2】:

如果您希望将 XML 作为 XML 而不是作为字符数据包含在内,则必须在某个时候对其进行解析。如果您不想自己手动进行解析,您有两种选择:

(1) 使用外部解析实体——在这种情况下,外部文件将被 XML 解析器拉入并解析。当输出再次序列化时,它将包含外部文件的内容。

[见http://www.javacommerce.com/displaypage.jsp?name=entities.sql&id=18238]

(2) 使用 Xinclude -- 在这种情况下,文件必须通过 xinclude 处理器运行,该处理器会将 xinclude 引用合并到输出中。大多数 xslt 处理器以及 xmllint 也会使用适当的选项执行 xinclude。

[参见:http://www.xml.com/pub/a/2002/07/31/xinclude.html]

(XSLT 也可用于合并文档而不使用 XInclude 语法。XInclude 只是提供标准语法)

【讨论】:

    【解决方案3】:

    问题不是“这里”,而是&lt;b&gt;&lt;/b&gt;

    &lt;b&gt; 元素添加为内容的子元素,您就可以做到这一点。任何像 JDOM 或 DOM4J 这样的库都允许你这样做。一般情况是将内容解析为 XML DOM,并将根元素添加为 &lt;contents&gt; 的子元素。

    您不能在 CDATA 部分之外添加转义值。

    【讨论】:

      【解决方案4】:

      如果您想在 XML 文档中嵌入大型 HTML 文档,那么 CDATA imho 是您的最佳选择。这样您就不必了解或处理内部结构,并且您可以稍后将文档类型从 HTML 更改为其他内容,而无需太多麻烦。 我认为你也不能嵌入例如DOCTYPE 指令直接(即作为保留 DOCTYPE 指令语义的结构化数据)。它们必须表示为字符。

      (这主要是对您的更新的回应,但可惜我没有足够的代表发表评论......)

      【讨论】:

        【解决方案5】:

        我看不出解析要插入到输出中的大 XML 块有什么问题。使用 StAX 解析器对其进行解析,只需编写代码将所有事件转发到您现有的序列化程序(变量“xtw”)。

        【讨论】:

          【解决方案6】:

          如果 html 的 blob 实际上是 xhtml,那么我建议做类似的事情(在伪代码中):

          xtw.writeStartElement("contents")
          XMLReader  xtr=new XMLReader();
          xtr.read(blob);
          Dom dom=xtr.getDom();
          for(element e:dom){
              xtw.writeElement(e);
          }
          xtw.writeEndElement();
          

          或类似的东西。我不得不做一次类似的事情,但使用了不同的库。

          【讨论】:

            【解决方案7】:

            如果你的 XML 和 HTML 不是太大,你可以做一个解决方法:

            xtw.writeStartElement("contents");
            xtw.writeCharacters("anUniqueIdentifierForReplace"); // <--
            xtw.writeEndElement();
            

            当您将 XML 作为字符串时:

            xmlAsString.replace("anUniqueIdentifierForReplace", yourHtmlAsString);
            

            我知道,这不是很好,但这可以工作。


            编辑:当然,您应该检查yourHtmlAsString 是否有效。

            【讨论】:

            • 非常聪明!谢谢你的想法。
            • 这实际上是一个非常愚蠢的 hack。如果您不希望 XML 编写器生成有效的 XML 文档,请改用字符串连接。
            • 如果您知道您有有效的 XML 可以作为 blob 输入,这将起作用,但您要承担格式正确的风险。
            • 好的!好的!我不会用这个。无需再对丹尼尔投反对票。
            • 任何计算机程序都遵守“Garbage In Garbage Out”规则。这个解决方案也不差。要么你有有效的输入,然后这个解决方案比其他解决方案更有效,要么你没有,在这种情况下,这里提出的所有解决方案都无法生成有效的 XML 输出。所以,这个解决方案绝对更好。
            猜你喜欢
            • 2020-04-04
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-11-28
            • 2015-06-30
            • 1970-01-01
            • 1970-01-01
            • 2023-03-21
            相关资源
            最近更新 更多