我想知道是否有办法在xml文档的CDATA部分中转义CDATA结束标记( ]]>
) . 或者,更一般地说,如果在CDATA中使用某些转义序列(但如果它存在,我想它可能只有在逃避开始或结束令牌时才有意义) .
基本上,您是否可以在CDATA中嵌入开始或结束标记,并告诉解析器不要解释它,而是将其视为另一个字符序列 .
可能你应该重构你的xml结构或你的代码,如果你发现自己试图这样做,但即使我在过去3年左右每天都在使用xml而且我从来没有遇到过这个问题,我想知道是否有可能 . 只是出于好奇 .
编辑:
除了使用html编码...
10 回答
另一种解决方案是将
]]>
替换为]]]><![CDATA[]>
.看到这个结构:
对于内部CDATA标记,您必须使用
]]]]><![CDATA[>
而不是]]>
关闭 . 就那么简单 .显然,这个问题纯粹是学术性的 . 幸运的是,它有一个非常明确的答案 .
您无法转义CDATA结束序列 . XML specification的 生产环境 规则20非常清楚:
编辑:此产品规则字面意思是“CData部分可能包含任何你想要的但是序列']]>' . 没有例外 . ”
EDIT2:same section还读取:
换句话说,不可能使用实体引用,标记或任何其他形式的解释语法 . CDATA部分中唯一解析的文本是
]]>
,它终止该部分 .因此,无法在CDATA部分内逃避
]]>
.编辑3:same section也读到:
然后可能存在CDATA部分,可能出现任何字符数据,包括单个CDATA部分的多个相邻CDATA部分 . 这使得可以分割
]]>
令牌并将其两部分放在相邻的CDATA部分中 .例如:
应该写成
你必须将你的数据分成碎片以隐藏
]]>
.这是整个事情:
<![CDATA[]]]]><![CDATA[>]]>
第一个
<![CDATA[]]]]>
有]]
. 第二个<![CDATA[>]]>
有>
.你没有逃避
]]>
,但是在]]
之后通过在>
之前插入]]><![CDATA[
来逃避>
,想想这就像C / Java / PHP / Perl字符串中的\
,但只需要在>
之前和]]
之后 .顺便说一句,
S.Lott的回答与此相同,措辞不同 .
S. Lott的答案是正确的:你没有对结束标记进行编码,而是在多个CDATA部分中对其进行分解 .
如何在现实世界中遇到这个问题:使用XML编辑器创建一个将被送入内容管理系统的XML文档,尝试写一篇关于CDATA部分的文章 . 你在CDATA部分嵌入代码示例的普通技巧将在这里失败 . 你可以想象我是如何学到这一点的 .
但在大多数情况下,你不会遇到这个,这就是原因:如果你想将XML文档的文本存储(比方说)作为XML元素的内容,你可能会使用DOM方法,例如:
DOM完全合理地逃脱了<和>,这意味着你没有无意中在文档中嵌入了CDATA部分 .
哦,这很有趣:
这可能是.NET DOM的一种特殊情况,但这不会引发异常 . 抛出异常:
我猜在幕后发生的事情是XmlDocument使用XmlWriter产生它的输出,并且XmlWriter在写入时检查格式良好 .
只需将
]]>
替换为]]]]><![CDATA[>
这是另一个需要转义
]]>
的案例 . 假设我们需要在XML文档的CDATA块中保存一个完全有效的HTML文档,并且HTML源恰好拥有它自己的CDATA块 . 例如:注释的CDATA后缀需要更改为:
因为XML解析器不会知道如何处理javascript注释块
在PHP中:
'<![CDATA['.implode(explode(']]>', $string), ']]]]><![CDATA[>').']]>'
PHP中更简洁的方法:
如果需要,请不要忘记使用多字节安全的str_replace(非latin1
$string
):