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

如何在已有模板的XSLT中重命名XML元素

解决XSLT嵌套模板报错并实现元素重命名

问题描述

需要将XML中的<NAME>元素重命名为<CD-NAME>,同时将该元素放入<info>节点下,但编写的XSLT因在模板内部嵌套模板报错,错误提示为:Element xsl:template must be top-level。

输入XML

<?xml version="1.0" encoding="UTF-8"?>
<CD xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <NAME>Empire Burlesque</NAME>
</CD>

错误的XSLT尝试

<?xml version="1.0" encoding="UTF-8"?>
<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:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()" />
        </xsl:copy>
    </xsl:template>
    
    <xsl:template match="/CD">
        <xsl:variable name="id"
            select="*[contains(local-name(), 'NAME')]"/>
        <CD>
            <info>
                <xsl:copy-of select="$id" copy-namespaces="no"/>
                <xsl:template match="CD/NAME">
                    <CD-NAME><xsl:apply-templates select="@*|node()" /></CD-NAME>
                </xsl:template> 
            </info>
        </CD>
    </xsl:template>
</xsl:stylesheet>

错误原因

XSLT规范要求<xsl:template>必须是顶级元素,即直接作为<xsl:stylesheet>的子元素,不能嵌套在其他模板或节点内部。你之前将匹配<NAME>的模板放在了匹配/CD的模板内部,违反了语法规则,导致报错。

正确解决方案

把重命名的模板单独作为顶级元素,同时调整/CD模板的逻辑,用<xsl:apply-templates>触发重命名模板,而非直接复制原元素。

修正后的XSLT

<?xml version="1.0" encoding="UTF-8"?>
<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:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

    <!-- 身份模板:默认复制所有节点和属性 -->
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <!-- 处理根CD节点,生成外层结构并触发内部元素的模板 -->
    <xsl:template match="/CD">
        <CD>
            <info>
                <!-- 应用模板到NAME元素,触发重命名模板 -->
                <xsl:apply-templates select="NAME"/>
            </info>
        </CD>
    </xsl:template>

    <!-- 顶级模板:将NAME元素重命名为CD-NAME -->
    <xsl:template match="NAME">
        <CD-NAME>
            <xsl:apply-templates select="@*|node()"/>
        </CD-NAME>
    </xsl:template>
</xsl:stylesheet>

期望输出

<?xml version="1.0" encoding="UTF-8"?>
<CD>
   <info>
      <CD-NAME>Empire Burlesque</CD-NAME>
   </info>
</CD>

关键说明

  1. 身份模板:保留默认的节点复制逻辑,确保未被特殊模板匹配的节点原样输出。
  2. /CD模板:重新构建外层的<CD>和<info>结构,通过<xsl:apply-templates select="NAME">触发重命名模板,而非xsl:copy-of(后者会直接复制原元素,不会触发任何模板)。
  3. NAME重命名模板:作为顶级模板,匹配所有<NAME>元素,将其替换为<CD-NAME>并保留内部内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 21:15:31