如何修改XML中CDATA嵌入的XSLT样式表内的狗名?
解决XML中CDATA内文本替换的正确XSLT 3.0实现
核心思路
无需将CDATA内容转换为节点集,直接对CDATA的文本内容做字符串替换,同时确保输出时重新包裹CDATA标签,保留原XML结构与命名空间。
输入XML示例
<root> <some_other_element>保留内容</some_other_element> <dogs_stylesheet><![CDATA[ <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <dog> <name>Rover</name> </dog> </xsl:template> </xsl:stylesheet> ]]></dogs_stylesheet> </root>
正确XSLT 3.0代码
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 浅复制所有未匹配的节点,保留原结构 --> <xsl:mode on-no-match="shallow-copy"/> <!-- 专门处理dogs_stylesheet元素 --> <xsl:template match="dogs_stylesheet"> <xsl:copy> <!-- 输出CDATA起始标记,禁用转义确保标签原样输出 --> <xsl:text disable-output-escaping="yes"><![CDATA[</xsl:text> <!-- 替换文本中的Rover为Cerberus --> <xsl:value-of select="replace(., 'Rover', 'Cerberus')"/> <!-- 输出CDATA结束标记 --> <xsl:text disable-output-escaping="yes">]]></xsl:text> </xsl:copy> </xsl:template> </xsl:stylesheet>
问题解决说明
- CDATA标签缺失问题:通过
disable-output-escaping="yes"手动输出CDATA的起止标记,确保修改后的内容被正确包裹在CDATA中。 - 不必要命名空间插入:使用
shallow-copy模式复制原节点结构,且直接处理文本而非解析CDATA内的XSLT节点,避免额外命名空间注入。 - CDATA转节点集问题:无需转换节点集,直接用
replace()函数对CDATA的原始文本做字符串替换,简化逻辑同时避免节点解析带来的副作用。
输出结果
<root> <some_other_element>保留内容</some_other_element> <dogs_stylesheet><![CDATA[ <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <dog> <name>Cerberus</name> </dog> </xsl:template> </xsl:stylesheet> ]]></dogs_stylesheet> </root>
内容的提问来源于stack exchange,提问作者woodduck
相关产品推荐
相关产品推荐

