XSLT - 多个子节点中的分组和求和

XSLT - Group and Sum in multiple childnode

正在尝试对 BalanceList 进行 XSLT 转换 xml。

输入由子元素构成,以从产品 -> 批次 -> 位置(使用 StockResevationKey)深入了解详细信息。

输出需要通过 BatchId 和 StockResevationKey(如果存在)对重复产品元素进行分组和求和

因此,“唯一产品数量”将通过以下方式识别: ExtProductId + BatchId + StockResevationKey (BatchId 和 StockResevationKey 并不总是出现在所有产品上)。

输入xml:

<?xml version="1.0" encoding="utf-8"?>
<BalanceList>
    <TransactionId>20642</TransactionId>
    <Products>
        <Product>
            <Quantity>100.000</Quantity>     
            <ProductText>Item_1</ProductText>
            <ExtProductId>0320366</ExtProductId>
            <ExtId/>
            <Batches>
                <Batch>
                    <Quantity>80.000</Quantity>       
                    <BatchId>1234</BatchId>
                    <ProductLocations>
                        <ProductLocation>
                            <ExtLocationId>100362-01-01</ExtLocationId>
                            <Quantity>20.000</Quantity>                         
                            <StockReservationKey>1111</StockReservationKey>
                        </ProductLocation>
                        <ProductLocation>
                            <ExtLocationId>100359-01-01</ExtLocationId>
                            <Quantity>40.000</Quantity>
                            <StockReservationKey>1111</StockReservationKey>
                        </ProductLocation>
                        <ProductLocation>
                            <ExtLocationId>100368-01-01</ExtLocationId>
                            <Quantity>20.000</Quantity>
                            <StockReservationKey>2222</StockReservationKey>
                        </ProductLocation>
                    </ProductLocations>
                </Batch>
                <Batch>
                    <Quantity>20.000</Quantity>
                    <BatchId>2345</BatchId>
                    <ProductLocations>
                        <ProductLocation>
                            <ExtLocationId>100897-01-01</ExtLocationId>
                            <Quantity>10.000</Quantity>
                            <StockReservationKey>2222</StockReservationKey>
                        </ProductLocation>
                        <ProductLocation>
                            <ExtLocationId>104567-01-01</ExtLocationId>
                            <Quantity>10.000</Quantity>
                            <StockReservationKey />
                        </ProductLocation>
                    </ProductLocations>
                </Batch>
            </Batches>
        </Product>
        <Product>
            <Quantity>200.000</Quantity>
            <ProductText>Item_2</ProductText>
            <ExtProductId>0358523</ExtProductId>
            <ExtId/>
            <Batches>
                <Batch>
                    <Quantity>100.000</Quantity>
                    <BatchId>222</BatchId>
                    <ProductLocations>
                        <ProductLocation>
                            <ExtLocationId>100365-01-01</ExtLocationId>
                            <Quantity>100.000</Quantity>
                            <StockReservationKey/>
                        </ProductLocation>
                    </ProductLocations>
                </Batch>
                <Batch>
                    <Quantity>100.000</Quantity>
                    <BatchId>333</BatchId>
                    <ProductLocations>
                        <ProductLocation>
                            <ExtLocationId>100399-01-01</ExtLocationId>
                            <Quantity>100.000</Quantity>
                            <StockReservationKey/>
                        </ProductLocation>
                    </ProductLocations>
                </Batch>
            </Batches>
        </Product>
    </Products>
</BalanceList>

想要的结果:

<?xml version="1.0" encoding="utf-8"?>
<BalanceList>
    <TransactionId>20642</TransactionId>
    <Product>
        <ProductText>Item_1</ProductText>
        <ExtProductId>0320366</ExtProductId>  --(Concat key = 0320366+1234+1111)
        <Quantity>60.000</Quantity>
        <BatchId>1234</BatchId>
        <StockReservationKey>1111</StockReservationKey>
    </Product>
    <Product>
        <ProductText>Item_1</ProductText>
        <ExtProductId>0320366</ExtProductId>  --(Concat key = 0320366+1234+2222)
        <Quantity>20.000</Quantity>
        <BatchId>1234</BatchId>
        <StockReservationKey>2222</StockReservationKey>
    </Product>
    <Product>
        <ProductText>Item_1</ProductText>
        <ExtProductId>0320366</ExtProductId>   --(Concat key = 0320366+2345+2222)
        <Quantity>10.000</Quantity>
        <BatchId>2345</BatchId>
        <StockReservationKey>2222</StockReservationKey>
    </Product>
    <Product>
        <ProductText>Item_1</ProductText>
        <ExtProductId>0320366</ExtProductId>   --(Concat key = 0320366+2345)
        <Quantity>10.000</Quantity>
        <BatchId>2345</BatchId>
        <StockReservationKey/>
    </Product>
    
    <Product>
        <ProductText>Item_2</ProductText>
        <ExtProductId>0358523</ExtProductId>   --(Concat key = 0358523+222)
        <Quantity>100.000</Quantity>
        <BatchId>222</BatchId>
        <StockReservationKey/>
    </Product>
    <Product>
        <ProductText>Item_2</ProductText>
        <ExtProductId>0358523</ExtProductId>   --(Concat key = 0358523+333)
        <Quantity>100.000</Quantity>
        <BatchId>333</BatchId>
        <StockReservationKey/>
    </Product>
    
    <Product>
        <ProductText>Item_3</ProductText>
        <ExtProductId>0358500</ExtProductId>   --(Concat key = 0358500)
        <Quantity>50.000</Quantity>
        <BatchId/>
        <StockReservationKey/>
    </Product>
</BalanceList>  

到目前为止,我已经走到这一步了,但无法弄清楚使总和正确以及要显示的下一个产品的最后步骤。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>
    <xsl:key name="ProductGroup" match="BalanceList/Products/Product" use="ExtProductId"/>
    <xsl:key name="ProductBatchGroup" match="BalanceList/Products/Product/Batches/Batch" use="BatchId"/>
    <xsl:key name="ProductLocationGroup" match="BalanceList/Products/Product/Batches/Batch/ProductLocations/ProductLocation" use="StockReservationKey"/>
    <xsl:template match="/">
        <BalanceList>
            <Products>
                <xsl:for-each select="BalanceList/Products/Product[generate-id() = generate-id(key('ProductGroup', ExtProductId)[1])]">
                    <xsl:for-each select="Batches/Batch[generate-id() = generate-id(key('ProductBatchGroup', BatchId)[1])]">
                        <xsl:for-each select="ProductLocations/ProductLocation[generate-id() = generate-id(key('ProductLocationGroup', StockReservationKey)[1])]">
                        <xsl:variable name="Reservation-group" select="ProductLocations/ProductLocation[StockReservationKey = current()/StockReservationKey]"/>
                            <Product>
                                <ProductText>
                                    <xsl:value-of select="../../../../ProductText"/>
                                </ProductText>
                                <ExtProductId>
                                    <xsl:value-of select="../../../../ExtProductId"/>
                                </ExtProductId>
                                <BatchId>
                                    <xsl:value-of select="../../BatchId"/>
                                </BatchId>
                                <StockReservationKey>
                                    <xsl:value-of select="StockReservationKey"/>
                                </StockReservationKey>
                                <Quantity>
                                    <xsl:value-of select="sum(Quantity)"/>
                                </Quantity>
                            </Product>
                        </xsl:for-each>
                    </xsl:for-each>
                </xsl:for-each>
            </Products>
        </BalanceList>
    </xsl:template>
</xsl:stylesheet>

AFAICT,以下样式表可以满足您的需求:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:key name="k1" match="ProductLocation" use="concat(ancestor::Product/ExtProductId, '|', ancestor::Batch/BatchId, '|', StockReservationKey)"/>

<xsl:template match="/BalanceList">
    <xsl:copy>
        <xsl:copy-of select="TransactionId"/>
        <xsl:for-each select="Products/Product/Batches/Batch/ProductLocations/ProductLocation[generate-id() = generate-id(key('k1', concat(ancestor::Product/ExtProductId, '|', ancestor::Batch/BatchId, '|', StockReservationKey))[1])]">
            <Product>
                <xsl:copy-of select="ancestor::Product/ProductText"/>
                <xsl:copy-of select="ancestor::Product/ExtProductId"/>
                <xsl:copy-of select="ancestor::Batch/BatchId"/>
                <xsl:copy-of select="StockReservationKey"/>
                <Quantity>
                    <xsl:value-of select="sum(key('k1', concat(ancestor::Product/ExtProductId, '|', ancestor::Batch/BatchId, '|', StockReservationKey))/Quantity)"/>
                </Quantity>
            </Product>
        </xsl:for-each>
    </xsl:copy>                    
</xsl:template>

</xsl:stylesheet>