使用XSL移除/修正XML空xmlns 避免子元素生成空命名空间的方案
空xmlns属性修正的XSL实现方案
原有方案的问题根因
之前使用的XSL样式表在处理level2元素时,直接通过xsl:copy-of硬拷贝其下属所有节点。由于原输入XML中level2携带xmlns=""属性,其内部的所有子元素、属性实际均归属到空命名空间。当手动将level2放置到http://tempuri.org/业务命名空间下时,XSLT处理器为了维持被拷贝节点的原始命名空间归属,会自动在每个跨命名空间的子元素上生成xmlns=""声明,最终出现修正了父元素、却在子元素上残留空xmlns的问题。
有效修正的XSL代码
该方案不依赖硬匹配特定层级的元素,可自动识别所有空命名空间的节点,将其统一映射到目标业务命名空间,全程不残留任何空xmlns属性,且兼容XSLT 1.0/2.0版本:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:target="http://tempuri.org/" exclude-result-prefixes="target"> <xsl:output encoding="UTF-8" indent="yes" method="xml"/> <!-- 处理原本就属于业务命名空间的节点,保持原样输出 --> <xsl:template match="target:* | @target:*"> <xsl:copy> <xsl:apply-templates select="@* | node()"/> </xsl:copy> </xsl:template> <!-- 核心修正逻辑:所有空命名空间的元素,统一重映射到目标业务命名空间 --> <xsl:template match="*[namespace-uri() = '']"> <xsl:element name="{local-name()}" namespace="http://tempuri.org/"> <xsl:apply-templates select="@* | node()"/> </xsl:element> </xsl:template> <!-- 处理空命名空间下的属性,直接绑定到当前输出上下文 --> <xsl:template match="@*[namespace-uri() = '']"> <xsl:attribute name="{local-name()}"> <xsl:value-of select="."/> </xsl:attribute> </xsl:template> </xsl:stylesheet>
实际输出效果
经过该样式表处理后的XML结构完全符合要求,无任何空xmlns残留:
<?xml version="1.0" encoding="UTF-8"?> <rootElement xmlns="http://tempuri.org/"> <level1> <level2> <child1 id="aNumber" desc="aString"> <name>name1</name> <code>code1</code> </child1> <child2 desc="aString"> <field1>field1</field1> <field2>field2</field2> </child2> </level2> </level1> </rootElement>
方案优势
- 从根源避免跨命名空间硬拷贝导致的自动补空xmlns问题,所有原空命名空间节点会被显式创建到目标业务命名空间下
- 无需针对特定层级元素写单独修正规则,哪怕输入XML中空xmlns出现在任意深度的节点上,也能自动完成修正
- 原有业务命名空间下的节点不会被改动,完全保留原始XML的结构和内容
- 兼容更低版本的XSLT处理器,不需要依赖2.0版本的专属特性
内容的提问来源于stack exchange,提问作者juankinspain
相关产品推荐
相关产品推荐

