如何用XSLT移除CDATA内指定context的rule元素
解决方案:用XSLT移除CDATA中指定的rule元素
问题背景
需要移除XML中CDATA块内、context属性以GenericFailureAnnouncementName结尾的<rule>元素。之前直接取消CDATA转义再删除元素的方法无效,原因是CDATA内容在原始XML中被视为纯文本,无法直接用XPath匹配内部的XML节点。
可行XSLT脚本
核心思路是先将CDATA文本解析为XML文档,删除目标节点后再重新序列化为文本并包裹回CDATA,以下是完整代码:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 身份模板:默认复制所有节点和属性 --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <!-- 处理CDATA所在的文本节点 --> <xsl:template match="/validationRules/rule/text()"> <!-- 把CDATA文本解析成XML文档 --> <xsl:variable name="parsedSchema" select="parse-xml(.)"/> <!-- 对解析后的XML做节点移除处理 --> <xsl:variable name="processedSchema"> <xsl:apply-templates select="$parsedSchema" mode="process-schema"/> </xsl:variable> <!-- 把处理后的XML转回文本,重新包裹CDATA --> <xsl:text disable-output-escaping="yes"><![CDATA[</xsl:text> <xsl:value-of select="serialize($processedSchema)"/> <xsl:text disable-output-escaping="yes">]]></xsl:text> </xsl:template> <!-- 模式模板:处理解析后的Schematron内容 --> <xsl:template match="@*|node()" mode="process-schema"> <xsl:copy> <xsl:apply-templates select="@*|node()" mode="process-schema"/> </xsl:copy> </xsl:template> <!-- 匹配并移除目标rule元素 --> <xsl:template match="rule[ends-with(@context, 'GenericFailureAnnouncementName')]" mode="process-schema"/> </xsl:stylesheet>
代码说明
- 身份模板:保证原始XML中除CDATA文本节点外,其他所有内容原样复制。
- CDATA解析与重构:
- 用
parse-xml()将CDATA内的纯文本转为可操作的XML节点集。 - 在
process-schema模式下过滤掉目标<rule>元素。 - 用
serialize()将处理后的XML转回文本,再手动添加CDATA标记(disable-output-escaping="yes"确保标记不被转义)。
- 用
- 目标节点匹配:通过
ends-with()精准定位需要删除的<rule>,匹配到后直接不输出该节点。
注意事项
- 该脚本需要XSLT 2.0及以上版本支持,因为用到了
parse-xml()和serialize()函数。 - 若仅支持XSLT 1.0,需借助EXSLT扩展函数配合字符串处理实现,复杂度会更高。
内容的提问来源于stack exchange,提问作者Valli Annamalai
相关产品推荐
相关产品推荐

