You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何移除XSLT输出中的xmlns:xsi命名空间声明?

如何移除XSLT转换输出中的xmlns:xsi声明

问题场景

XSLT转换后,输出的子元素上自动带上了xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"声明,需要将其移除。

输入XML

<?xml version="1.0" encoding="UTF-8"?>
<items xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="items_schema.xsd"> 
    <Skyscraper>Willis Tower</Skyscraper> 
    <Small_fruit>blueberry</Small_fruit> 
    <Big_fruit>watermelon </Big_fruit> 
</items>

原XSLT代码

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="xs"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" version="2.0">
            
            <xsl:template match="/items">   
                <xsl:variable name="fruit" select="*[contains(local-name(), 'fruit')]" />   
                <items>
                    <Building>
                        <xsl:copy-of select="* except $fruit"/>
                    </Building>
                    <Food>
                        <xsl:copy-of select="$fruit"/>
                    </Food>
                </items>
            </xsl:template>
            
        </xsl:stylesheet>

实际输出XML

<items> 
    <Building>
        <Skyscraper xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Willis Tower</Skyscraper>
    </Building> 
    <Food>
        <Small_fruit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">blueberry</Small_fruit> 
        <Big_fruit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">watermelon </Big_fruit> 
    </Food>
</items>

期望输出XML

<items> 
    <Building>
        <Skyscraper>Willis Tower</Skyscraper>
    </Building> 
    <Food>
        <Small_fruit>blueberry</Small_fruit> 
        <Big_fruit>watermelon </Big_fruit> 
    </Food>
</items>

解决方案

出现这个问题的核心原因是:原XML根节点带有xsi命名空间,<xsl:copy-of>默认会复制节点的命名空间上下文,即使子节点本身没有使用该命名空间,也会被自动带上。

方法一:自定义模板复制节点(兼容XSLT 1.0)

如果你的处理器仅支持XSLT 1.0,可以通过自定义模板递归复制节点,同时排除xsi命名空间及相关属性:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                exclude-result-prefixes="xs xsi"
                xmlns:xs="http://www.w3.org/2001/XMLSchema" 
                version="1.0">

    <!-- 匹配所有元素节点,复制时排除xsi命名空间 -->
    <xsl:template match="*">
        <xsl:element name="{local-name()}">
            <!-- 复制除xsi前缀外的所有属性 -->
            <xsl:copy-of select="@*[not(namespace-uri() = 'http://www.w3.org/2001/XMLSchema-instance')]"/>
            <!-- 递归处理子节点和文本 -->
            <xsl:apply-templates/>
        </xsl:element>
    </xsl:template>

    <!-- 匹配文本节点直接复制 -->
    <xsl:template match="text()">
        <xsl:copy/>
    </xsl:template>

    <xsl:template match="/items">   
        <xsl:variable name="fruit" select="*[contains(local-name(), 'fruit')]" />   
        <items>
            <Building>
                <xsl:apply-templates select="* except $fruit"/>
            </Building>
            <Food>
                <xsl:apply-templates select="$fruit"/>
            </Food>
        </items>
    </xsl:template>

</xsl:stylesheet>

方法二:使用copy-namespaces="no"属性(XSLT 2.0+)

如果你的处理器支持XSLT 2.0及以上,直接在<xsl:copy-of>中添加copy-namespaces="no"属性即可,这是最简洁的处理方式:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="xs"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" version="2.0">
            
    <xsl:template match="/items">   
        <xsl:variable name="fruit" select="*[contains(local-name(), 'fruit')]" />   
        <items>
            <Building>
                <xsl:copy-of select="* except $fruit" copy-namespaces="no"/>
            </Building>
            <Food>
                <xsl:copy-of select="$fruit" copy-namespaces="no"/>
            </Food>
        </items>
    </xsl:template>
            
</xsl:stylesheet>

copy-namespaces="no"的作用是复制节点时不复制其继承的命名空间声明,直接避免子节点带上xsi的命名空间。


内容的提问来源于stack exchange,提问作者n718an

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 05:13:21