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

XSL替换单个元素命名空间URI并保留前缀的实现问题

问题描述

原XML文档:

<?xml version='1.0' encoding='utf-8'?>
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
    <env:Body>
        <wd:Unpost_Job_Request
            xmlns:wd="urn:com.test.report"
            wd:version="v40.2">
            <wd:Business_Process_Parameters>
                <wd:Auto_Complete>true</wd:Auto_Complete>
                <wd:Run_Now>true</wd:Run_Now>
                <wd:Discard_On_Exit_Validation_Error>true</wd:Discard_On_Exit_Validation_Error>
                <wd:Comment_Data>
                    <wd:Comment>Unposting Triggered by Automation</wd:Comment>
                </wd:Comment_Data>
            </wd:Business_Process_Parameters>
            <wd:Unpost_Job_Data>
                <wd:Job_Posting_Reference>
                    <wd:ID wd:type="Job_Posting_ID">JOB_POSTING-3-23427</wd:ID>
                </wd:Job_Posting_Reference>
            </wd:Unpost_Job_Data>
        </wd:Unpost_Job_Request>
    </env:Body>
</env:Envelope>

需求:完整复制整个文档,仅将<wd:Unpost_Job_Request>元素及其所有子元素、属性的命名空间从urn:com.test.report替换为urn:com.final.report,预期输出如下:

<?xml version='1.0' encoding='utf-8'?>
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
    <env:Body>
        <wd:Unpost_Job_Request
            xmlns:wd="urn:com.final.report"
            wd:version="v40.2">
            <wd:Business_Process_Parameters>
                <wd:Auto_Complete>true</wd:Auto_Complete>
                <wd:Run_Now>true</wd:Run_Now>
                <wd:Discard_On_Exit_Validation_Error>true</wd:Discard_On_Exit_Validation_Error>
                <wd:Comment_Data>
                    <wd:Comment>Unposting Triggered by Automation</wd:Comment>
                </wd:Comment_Data>
            </wd:Business_Process_Parameters>
            <wd:Unpost_Job_Data>
                <wd:Job_Posting_Reference>
                    <wd:ID wd:type="Job_Posting_ID">JOB_POSTING-3-23427</wd:ID>
                </wd:Job_Posting_Reference>
            </wd:Unpost_Job_Data>
        </wd:Unpost_Job_Request>
    </env:Body>
</env:Envelope>

原使用的XSL:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:wd="urn:com.test.report"
    exclude-result-prefixes="xs" version="2.0">

    <xsl:output indent="yes" method="xml" encoding="utf-8" omit-xml-declaration="yes"/>

    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="wd:Unpost_Job_Request">
        <xsl:element name="{local-name(.)}">
            <xsl:namespace name="wd">urn:com.final.report</xsl:namespace>
            <xsl:apply-templates select="node() | @*"/>
        </xsl:element>
    </xsl:template>

</xsl:stylesheet>

问题:转换后未替换原有命名空间,反而新增命名空间,旧命名空间被添加_1后缀,子元素仍绑定旧命名空间,无法达到预期效果。

正确XSL实现方案
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:oldwd="urn:com.test.report"
    xmlns:wd="urn:com.final.report"
    exclude-result-prefixes="oldwd" version="2.0">

    <xsl:output indent="yes" method="xml" encoding="utf-8" omit-xml-declaration="no"/>

    <!-- 基础复制模板:复制未匹配特殊规则的节点和属性 -->
    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>

    <!-- 替换根目标元素的命名空间 -->
    <xsl:template match="oldwd:Unpost_Job_Request">
        <wd:Unpost_Job_Request>
            <xsl:apply-templates select="@*">
                <xsl:with-param name="new-ns" select="'urn:com.final.report'"/>
            </xsl:apply-templates>
            <xsl:apply-templates select="node()">
                <xsl:with-param name="new-ns" select="'urn:com.final.report'"/>
            </xsl:apply-templates>
        </wd:Unpost_Job_Request>
    </xsl:template>

    <!-- 替换所有旧命名空间下的子元素 -->
    <xsl:template match="oldwd:*">
        <xsl:param name="new-ns"/>
        <xsl:element name="wd:{local-name()}" namespace="{$new-ns}">
            <xsl:apply-templates select="@*">
                <xsl:with-param name="new-ns" select="$new-ns"/>
            </xsl:apply-templates>
            <xsl:apply-templates select="node()">
                <xsl:with-param name="new-ns" select="$new-ns"/>
            </xsl:apply-templates>
        </xsl:element>
    </xsl:template>

    <!-- 替换所有旧命名空间下的属性 -->
    <xsl:template match="@oldwd:*">
        <xsl:param name="new-ns"/>
        <xsl:attribute name="wd:{local-name()}" namespace="{$new-ns}">
            <xsl:value-of select="."/>
        </xsl:attribute>
    </xsl:template>

</xsl:stylesheet>
方案说明
  1. 命名空间区分:将原wd命名空间重命名为oldwd,新命名空间直接绑定为wd,避免命名冲突导致的前缀自动添加后缀问题。
  2. 全范围替换:不仅替换目标元素本身,还递归替换其所有子元素和属性的命名空间,确保整个分支都切换到新命名空间。
  3. 输出配置:将omit-xml-declaration设为no,保证输出包含XML声明,与预期格式完全一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 03:45:02