XSLT 生成 XML 中带 CDATA 的节点

原来曾经都是用代码或是像 Velocity 样的模板来转换生成 XML的,自从接触了 XSLT 后,已把它当成了 XML 到其他许多数据格式的不二之选了。有时候因为特殊字符等因素,需要转换后的数据在新节点中用 <![CDATA[...]]> 包裹起来更好看且不易出错,或者还需对生成的 XML 进一步处理时,用 <![[CDATA[...]]> 会更保险些 。

通常我们在 xslt 文件中会这么写:

<description><xsl:value-of select="Description"/></description>

如果原来的 Description 中有特殊字符,如 < 等,转换后,< 会自动变为 &lt; 的,即得到

<description>Hello&lt;Unmi</description>

如果其中是一大段的 html 代码全部变为 &lt; &gt; 等就不怎么直观了,如果用 <![[CDATA[...]]> 就可呈现为原形。再有种情况,如果给 <xsl:value-of> 加个 disable-output-escaping= "yes " 属性,即不对 < 和 > 等符号转义,生成的新的 <description> 将可能是不合法的,例如:

<description>Hello<Unmi</description>,节点间含 < 等符号,不能正确解析。

再者,如果要对生成的 XML 数据作一次纯字符串的操作,不小心置入了特殊字符,该份 XML 将是非法的,所以还是用 <![[CDTA[...]]> 要稳妥。是不直接想过写成这样:

<description><![CDATA[<xsl:value-of select="Description"/>]]></description>

因为 xslt 本身就是个 XML 文档,上面等于把其中的 <xsl:value-of select="Description> 给注释掉了,生成的数据将会是:

<description>&lt;xsl:value-of select="Description"/&gt;</description>

那么给 <![CDATA[...]]> 的 < 和 > 号转义如何,也就是写成:

<description>&lt;![CDATA[<xsl:value-of select="Description"/>]]&gt;</description>

得到的结果将会是:

<description> &lt;![CDATA[Hello Unmi&gt;</description>

所以说,事情还没有到想当然中那么简单,有什么不决多问问香港的 Google,可以总结出以下两种方法:

1. cdata-section-elements 里写上要用 <![CDATA[...]]> 包裹内容的标签

要写在 <xsl:output 中,比如要让 <description> 标签中的内容包裹上 <![CDATA[...]]> 的话,就写成:

<xsl:output method="xml" cdata-section-elements="description"/>

那么在模板中,仍旧用 <description><xsl:value-of select="Description"/></description>,生成新的 <description> 节点就会是:

<description><![CDATA[Hello Unmi]]></description>

要是多个节点要使用 <![CDATA[...]]>,那就全部列在 cdata-section-elements 中即可,记得是用空格隔开。例如,还有个带命名空间的节点有同样的需求,这样写:

<xsl:output method="xml" indent="yes" cdata-section-elements="description content:encoded"/>

这样可使得 descriptioncontent:encoded 的数据内容都是 CDATA。有了 <![CDATA[...]]> 的护航,为 <xsl:value-of 里写上 disable-output-escaping="yes" 都不怕了。

2. 手工加上前后的 <![CDATA[ 和 ]]>,用到 disable-output-escaping="yes"

正好可以从前面的例子认识到了 disable-output-escaping="yes" 的效果,是否转义特殊字符,默认为 false,yes 为不转义,是 < 就显示为 <,而不是 &lt; 。具体写的代码复杂了些,多了几行:

这么多行,也就是和 <xsl:output method="xml" cdata-section-elements="description"/> 一样的效果,毋庸置疑,大家都会去选第一种方法。也许你可以让这里的 disable-output-escaping 在其他地方派上用场。

参考:http://topic.csdn.net/t/20061013/10/5079437.html

本文链接 https://yanbin.blog/xslt-generate-cdata-node/, 来自 隔叶黄莺 Yanbin Blog

[版权声明] Creative Commons License 本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。

Subscribe
Notify of
guest

1 Comment
Inline Feedbacks
View all comments