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

XSLT中for-each-group输出line_amount为多值的原因咨询

XSLT分组转换中line_amount输出多值的问题分析

问题描述

我是XSLT新手,在用for-each-group结合for-each做XML转换时,发现输出的lineitem-position能对应每个组元素输出单个值,但line_amount却输出所有值的列表。我期望line_amount和lineitem-position一样,每个条目输出单个对应值。

输入XML

<order order-no="60058554">
    <product-lineitems>
        <product-lineitem>
            <gross-price>76.00</gross-price>
            <position>1</position>
            <quantity unit=""></quantity>
            <custom-attributes>
                <custom-attribute attribute-id="associatedPromotionId">Reward1Band2</custom-attribute>
                <custom-attribute attribute-id="associatedPromotionId">Reward2Band3</custom-attribute>
            </custom-attributes>
            <price-adjustments>
                <price-adjustment>
                    <gross-price>-38.00</gross-price>
                    <promotion-id>Reward1Band2</promotion-id>
                </price-adjustment>
                <price-adjustment>
                    <gross-price>-38.00</gross-price>
                    <promotion-id>Reward2Band3</promotion-id>
                </price-adjustment>
            </price-adjustments>
        </product-lineitem>
        <product-lineitem>
            <gross-price>50.00</gross-price>
            <position>2</position>
            <quantity unit=""></quantity>
            <custom-attributes>
                <custom-attribute attribute-id="associatedPromotionId">Reward3Band3</custom-attribute>
            </custom-attributes>
            <price-adjustments>
                <price-adjustment>
                    <gross-price>-50.00</gross-price>
                    <promotion-id>Reward3Band3</promotion-id>
                </price-adjustment>
            </price-adjustments>
        </product-lineitem>
        <product-lineitem>
            <gross-price>28.00</gross-price>
            <position>3</position>
            <quantity unit=""></quantity>
            <custom-attributes>
                <custom-attribute attribute-id="associatedPromotionId">Reward2Band3</custom-attribute>
            </custom-attributes>
            <price-adjustments>
                <price-adjustment>
                    <gross-price>-28.00</gross-price>
                    <promotion-id>Reward2Band3</promotion-id>
                </price-adjustment>
            </price-adjustments>
        </product-lineitem>
    </product-lineitems>
</order>

XSLT代码

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="3.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns1="http://schemas.xmlsoap.org/soap/http" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xsi xsl ns1 soap wsdl xsd dw">
    
        <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="no"/>
        
        <xsl:template match="/dw:order">
            <xsl:variable name="associatedPromotions">
                <xsl:for-each-group select="dw:product-lineitems/dw:product-lineitem" group-by="dw:custom-attributes/dw:custom-attribute[@attribute-id='associatedPromotionId']">
                    <xsl:for-each select="current-group()">
                        <line>
                            <xsl:attribute name="lineitem-position">
                                <xsl:value-of select="dw:position"/>
                            </xsl:attribute>
                            <xsl:attribute name="line_amount">
                                <xsl:value-of select="dw:gross-price"/>
                            </xsl:attribute>
                        </line>
                    </xsl:for-each>
                </xsl:for-each-group>
            </xsl:variable>
        
        etc etc
   
    </xsl:template>
</xsl:stylesheet>

输出片段

<lineitem-position>1</lineitem-position>
<line_amount>76.00 76.00 28.00 50.00</line_amount>
    
<lineitem-position>1</lineitem-position>
<line_amount>76.00 76.00 28.00 50.00</line_amount>

<lineitem-position>3</lineitem-position>
<line_amount>76.00 76.00 28.00 50.00</line_amount>

<lineitem-position>2</lineitem-position>
<line_amount>76.00 76.00 28.00 50.00</line_amount>

问题原因及解决建议

核心原因

问题不在for-each-group的分组逻辑里,而是出在后续处理$associatedPromotions变量的代码中:

  1. 分组部分生成的<line>元素是正确的,每个元素的lineitem-position和line_amount属性都对应单个product-lineitem的数值。变量$associatedPromotions里会生成4个独立的<line>元素,每个元素的两个属性都是单个值。
  2. 你最终输出时,错误地全局选择了所有<line>元素的@line_amount属性(比如使用$associatedPromotions//@line_amount),而没有针对每个<line>元素提取它自身的@line_amount,导致每次输出都把所有line_amount值拼接成了列表。
  3. 而lineitem-position输出正确,是因为你针对每个<line>元素提取了自身的@lineitem-position属性(上下文是当前<line>元素)。

另外,你的XSLT代码存在一个潜在的致命问题:未声明dw命名空间前缀。代码中exclude-result-prefixes包含dw,但没有定义xmlns:dw="...",这会导致所有带dw:前缀的节点选择失效(比如dw:order、dw:product-lineitem等)。如果输入XML确实使用了dw命名空间,必须在<xsl:stylesheet>根元素中添加对应的命名空间声明,否则处理器无法匹配到目标节点。

解决方法

  1. 修复命名空间:在<xsl:stylesheet>根元素中添加dw命名空间的声明,确保与输入XML的命名空间一致,示例:
    xmlns:dw="http://你的命名空间URI"
    
  2. 修正输出逻辑:遍历$associatedPromotions中的每个<line>元素,针对每个元素提取自身的属性值,示例代码如下:
    <xsl:for-each select="$associatedPromotions/line">
        <lineitem-position><xsl:value-of select="@lineitem-position"/></lineitem-position>
        <line_amount><xsl:value-of select="@line_amount"/></line_amount>
    </xsl:for-each>
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 03:22:05