如何在保留现有命名空间的同时为XML根元素添加默认命名空间(xmlns)
如何在保留原有命名空间的同时为XML根节点添加默认命名空间
我来帮你解决这个问题!你遇到的情况是因为原来的XSLT把所有元素都强制移到了新的默认命名空间,而且没有保留根节点上原有的命名空间声明。咱们调整一下XSLT代码就能实现你要的效果:
问题分析
你原来的XSLT模板匹配了所有元素,每次都创建一个新元素并指定到新的默认命名空间,这就导致两个问题:
- 所有子元素的命名空间被错误地修改为新的默认命名空间(虽然示例结果里前缀还在,但实际命名空间已经变更)
- 根节点上原有的
xmlns:xs、xmlns:cac等命名空间声明完全丢失了
解决方案
我们需要只修改根节点的命名空间,同时保留它的所有原有命名空间属性,其他元素则直接复制,不改变它们的命名空间。修改后的XSLT代码如下:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output omit-xml-declaration="no" indent="yes"/> <xsl:strip-space elements="*"/> <xsl:variable name="vDefaultNS" select="'addedNamespace'"/> <!-- 专门处理根节点:添加默认命名空间,保留原有所有命名空间声明 --> <xsl:template match="/*"> <xsl:element name="{local-name()}" namespace="{$vDefaultNS}"> <!-- 复制根节点上的所有原有属性(包括命名空间声明) --> <xsl:copy-of select="@*"/> <!-- 递归处理子节点 --> <xsl:apply-templates/> </xsl:element> </xsl:template> <!-- 身份模板:复制所有其他节点,保持原有结构和命名空间 --> <xsl:template match="*|@*|text()|comment()|processing-instruction()"> <xsl:copy> <xsl:apply-templates select="*|@*|text()|comment()|processing-instruction()"/> </xsl:copy> </xsl:template> </xsl:stylesheet>
代码说明
- 根节点模板:只匹配XML的根节点,创建一个带有新默认命名空间的根元素,同时通过
<xsl:copy-of select="@*"/>完整复制根节点上原有的所有属性(包括所有xmlns:*形式的命名空间声明),确保原有命名空间不会丢失。 - 身份模板:这是XSLT中常用的技巧,匹配所有类型的节点(元素、属性、文本、注释等),直接复制它们的原样,保证子元素、属性和内容的结构与命名空间完全保留。
执行结果
运行上述XSLT后,你会得到完全符合期望的输出:
<?xml version="1.0" encoding="UTF-8"?> <RootNode xmlns="addedNamespace" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:cac="http://b/2" xmlns:cbc="http://a/2" xmlns:ns0="SomeNamespace" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <cbc:Element1>0000000001234567</cbc:Element1> <cbc:Element2>xxxxx</cbc:Element2> <cac:Element3> <cac:Element4> <cac:Element5> <cbc:Element6 schemeID="AAA">1234567890123</cbc:Element6> </cac:Element5> </cac:Element4> </cac:Element3> </RootNode>
(注:修正了你原XML中cbc:Element2的闭合标签错误)
内容的提问来源于stack exchange,提问作者Michael Kusters
相关产品推荐
相关产品推荐

