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

移除子节点多余命名空间:XML嵌套至ns0:OperationBody问题

解决方案:消除嵌套XML中的多余命名空间并满足转义要求

问题分析

当前XSLT存在两个核心问题导致多余命名空间输出:

  1. 遍历namespace::*时包含了从父元素继承的命名空间节点,导致子元素重复输出祖先已声明的命名空间(比如commonProvide元素上冗余的xmlns:ns1)。
  2. 硬编码了命名空间值,与输入XML中的实际命名空间(GlobalInteraction.xsdobjects)不符,且强制在根元素输出固定命名空间。

修正后的XSLT代码

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:ns0="serviceBusiness.xsdobjects.extload.services.classic.bt"
    xmlns:ns1="GlobalInteraction.xsdobjects"
    xmlns:commonProvide="commonentities.xsdobjects.extload"
    exclude-result-prefixes="xsl ns1 commonProvide">

    <!-- 主模板:生成ns0:OperationBody容器 -->
    <xsl:template match="/">
        <ns0:OperationBody>
            <xsl:apply-templates mode="escape"/>
        </ns0:OperationBody>
    </xsl:template>

    <!-- 元素转义模板:仅输出元素自身声明的命名空间,避免继承的冗余命名空间 -->
    <xsl:template match="*" mode="escape">
        <!-- 输出转义的起始标签左括号 -->
        <xsl:text>&lt;</xsl:text>
        <xsl:value-of select="name()"/>

        <!-- 输出元素自身直接声明的命名空间(排除继承的) -->
        <xsl:for-each select="namespace::*[not(. = ancestor::*/namespace::*[name()=current()/name()])]">
            <xsl:if test="name() != ''">
                <xsl:text> xmlns:</xsl:text>
                <xsl:value-of select="name()"/>
                <xsl:text>="</xsl:text>
                <xsl:value-of select="."/>
                <xsl:text>"</xsl:text>
            </xsl:if>
            <!-- 处理默认命名空间 -->
            <xsl:if test="name() = ''">
                <xsl:text> xmlns="</xsl:text>
                <xsl:value-of select="."/>
                <xsl:text>"</xsl:text>
            </xsl:if>
        </xsl:for-each>

        <!-- 结束起始标签 -->
        <xsl:text disable-output-escaping="yes">&gt;</xsl:text>

        <!-- 递归处理子节点 -->
        <xsl:apply-templates select="node()" mode="escape"/>

        <!-- 输出转义的结束标签 -->
        <xsl:text>&lt;/</xsl:text>
        <xsl:value-of select="name()"/>
        <xsl:text disable-output-escaping="yes">&gt;</xsl:text>
    </xsl:template>

    <!-- 文本节点转义模板 -->
    <xsl:template match="text()" mode="escape">
        <xsl:call-template name="escape-xml">
            <xsl:with-param name="text" select="."/>
        </xsl:call-template>
    </xsl:template>

    <!-- 通用XML转义模板 -->
    <xsl:template name="escape-xml">
        <xsl:param name="text"/>
        <xsl:if test="$text != ''">
            <xsl:variable name="head" select="substring($text, 1, 1)"/>
            <xsl:variable name="tail" select="substring($text, 2)"/>
            <xsl:choose>
                <xsl:when test="$head = '&amp;'">&amp;amp;</xsl:when>
                <xsl:when test="$head = '&lt;'">&amp;lt;</xsl:when>
                <xsl:when test="$head = '&gt;'">
                    <xsl:value-of select="'&amp;gt;'" disable-output-escaping="yes"/>
                </xsl:when>
                <xsl:when test="$head = '&quot;'">&amp;quot;</xsl:when>
                <xsl:when test="$head = '&apos;'">&amp;apos;</xsl:when>
                <xsl:otherwise>
                    <xsl:value-of select="$head"/>
                </xsl:otherwise>
            </xsl:choose>
            <xsl:call-template name="escape-xml">
                <xsl:with-param name="text" select="$tail"/>
            </xsl:call-template>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

关键修改说明

  1. 移除硬编码命名空间:不再固定输出预设的命名空间变量,而是通过namespace::*动态获取元素自身声明的命名空间,确保与输入XML完全一致。
  2. 过滤继承的命名空间:通过not(. = ancestor::*/namespace::*[name()=current()/name()])判断逻辑,只输出当前元素直接声明、且未在祖先元素中出现过的命名空间,彻底消除冗余。
  3. 修正前缀绑定:将XSLT中ns1的命名空间绑定改为输入XML中的GlobalInteraction.xsdobjects,匹配原始输入的命名空间结构。

预期输出

修正后的输出将严格保留输入XML中原本声明的命名空间,不会出现多余的xmlns:ns1在commonProvide元素上,同时完全满足起始标签转义为&lt;、结束标签保持>的要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 23:36:16