如何使用XSLT 1.0移除XML内联命名空间并添加对应前缀
用XSLT 1.0移除XML内联命名空间并添加对应前缀
需求概述
处理XML中带有内联默认命名空间声明的元素(如<OtherElement xmlns="test1Namespace">):
- 从根节点已有的命名空间前缀映射中,匹配该内联命名空间对应的前缀
- 为目标元素添加匹配到的前缀
- 移除元素上的内联命名空间声明,但保留元素的其他属性
- 其余XML节点保持原样
输入示例XML
<RootNode xmlns:test1="test1Namespace" xmlns:test2="childNamespace"> <test1:SomeElement> <OtherElement xmlns="test1Namespace"> <test2:ChildElement>test</test2:ChildElement> </OtherElement> </test1:SomeElement> </RootNode>
期望输出XML
<RootNode xmlns:test1="test1Namespace" xmlns:test2="childNamespace"> <test1:SomeElement> <test1:OtherElement> <test2:ChildElement>test</test2:ChildElement> </test1:OtherElement> </test1:SomeElement> </RootNode>
XSLT 1.0解决方案
<xsl:stylesheet version="1.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> <!-- 处理带内联默认命名空间的元素 --> <xsl:template match="*[namespace-uri() != '' and not(name() contains(':'))]"> <!-- 获取当前元素的命名空间URI --> <xsl:variable name="target-ns" select="namespace-uri()"/> <!-- 从根节点的命名空间映射中找到对应前缀 --> <xsl:variable name="prefix"> <xsl:for-each select="/namespace::*"> <xsl:if test="string(.) = $target-ns"> <xsl:value-of select="local-name()"/> </xsl:if> </xsl:for-each> </xsl:variable> <!-- 生成带前缀的目标元素 --> <xsl:element name="{$prefix}:{local-name()}" namespace="{$target-ns}"> <!-- 复制除内联命名空间外的所有属性 --> <xsl:apply-templates select="@*[not(namespace-uri() = 'http://www.w3.org/2000/xmlns/') or local-name() != 'xmlns']"/> <!-- 处理子节点 --> <xsl:apply-templates select="node()"/> </xsl:element> </xsl:template> </xsl:stylesheet>
代码说明
- 默认复制模板:确保所有未被特殊规则匹配的节点、属性都原样保留,保证XML结构的完整性。
- 内联命名空间处理逻辑:
- 匹配规则:筛选出有命名空间但无前缀的元素(即使用了内联默认命名空间的元素)
- 前缀匹配:遍历根节点的所有命名空间属性,找到与当前元素命名空间URI一致的前缀
- 元素重构:用匹配到的前缀重新命名元素,同时保留原命名空间URI
- 属性过滤:复制元素属性时排除内联的
xmlns声明,保留其他属性
内容的提问来源于stack exchange,提问作者salttoinjury
相关产品推荐
相关产品推荐

