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

XSLT 1.0 for-each循环choose变量判断结果不符合预期

XSLT 1.0 XML转换元素生成异常问题

基础信息

使用XSLT 1.0执行XML转换时,遍历节点生成子元素的判断逻辑未按当前遍历节点生效,只要输入文档中存在任意一个Type="A"的Product节点,所有遍历生成的子元素名称均为BoundComponent,不符合预期。

输入XML

<?xml version="1.0" encoding="UTF-8"?>
<Project ID="123">
  <ProductPool>
    <Product Type="A" ID="123" DueDate="123" Name="ABC"/>
    <Product Type="B" ID="123" DueDate="123" Name="ABC"/>
    <Product Type="A" ID="123" DueDate="123" Name="ABC"/>
    <Product Type="B" ID="123" DueDate="123" Name="ABC"/>
    <Product Type="A" ID="123" DueDate="123" Name="ABC"/>   
  </ProductPool>
</Project>

原有XSLT代码

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml" indent="yes"/>
    <xsl:template match="/">
        <xsl:element name="Product">
            <xsl:attribute name="ID">
                <xsl:value-of select="//Project/@ID"/>
            </xsl:attribute>
                <xsl:variable name="elem-name">
                    <xsl:choose>
                        <xsl:when test='//Product[@Type="A"]'>BoundComponent</xsl:when>
                        <xsl:otherwise>UnboundComponent</xsl:otherwise>
                    </xsl:choose>
                </xsl:variable>
                <xsl:for-each select="//Product">
                <xsl:element name="{$elem-name}">
                    <xsl:attribute name="ID">
                        <xsl:value-of select="@Name"/>
                    </xsl:attribute>
                    <xsl:attribute name="DueDate">
                        <xsl:value-of select="@DueDate"/>
                    </xsl:attribute>
                </xsl:element>
                </xsl:for-each>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

当前错误输出

<?xml version="1.0"?>
<Product ID="123">
  <BoundComponent ID="ABC" DueDate="123"/>
  <BoundComponent ID="ABC" DueDate="123"/>
  <BoundComponent ID="ABC" DueDate="123"/>
  <BoundComponent ID="ABC" DueDate="123"/>
  <BoundComponent ID="ABC" DueDate="123"/>
</Product>

预期规则

遍历每个Product节点时,根据节点自身的Type属性判断生成的元素名称:

  • Type属性值为A时,生成BoundComponent元素
  • 其余Type属性值时,生成UnboundComponent元素

问题原因

  • 变量elem-name定义在xsl:for-each循环外部,XSLT中变量是不可变的,只会在定义时计算一次值,不会随着循环内当前遍历节点的切换重新计算
  • 变量内的判断条件使用了全局绝对路径//Product[@Type="A"],该逻辑是判断整个文档中是否存在符合条件的节点,和当前遍历的节点没有关联,只要文档里有一个Type="A"的Product,判断结果就永远为真

修复方案

  1. 将元素名判断的变量定义移到xsl:for-each循环内部,让每次遍历节点时都基于当前上下文重新计算变量值
  2. 修改判断条件,直接读取当前遍历节点的@Type属性做判断,不再使用全局路径匹配

修复后XSLT代码

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml" indent="yes"/>
    <xsl:template match="/">
        <xsl:element name="Product">
            <xsl:attribute name="ID">
                <xsl:value-of select="//Project/@ID"/>
            </xsl:attribute>
            <xsl:for-each select="//Product">
                <xsl:variable name="elem-name">
                    <xsl:choose>
                        <xsl:when test="@Type='A'">BoundComponent</xsl:when>
                        <xsl:otherwise>UnboundComponent</xsl:otherwise>
                    </xsl:choose>
                </xsl:variable>
                <xsl:element name="{$elem-name}">
                    <xsl:attribute name="ID">
                        <xsl:value-of select="@Name"/>
                    </xsl:attribute>
                    <xsl:attribute name="DueDate">
                        <xsl:value-of select="@DueDate"/>
                    </xsl:attribute>
                </xsl:element>
            </xsl:for-each>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

修复后正确输出

<?xml version="1.0"?>
<Product ID="123">
  <BoundComponent ID="ABC" DueDate="123"/>
  <UnboundComponent ID="ABC" DueDate="123"/>
  <BoundComponent ID="ABC" DueDate="123"/>
  <UnboundComponent ID="ABC" DueDate="123"/>
  <BoundComponent ID="ABC" DueDate="123"/>
</Product>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.02 09:48:27