首页 > 解决方案 > Is it possible to group and sum segments/nodes in XSLT?

问题描述

With orders being received back, if an order line is split across two boxes, the company are returning the XML with some of the quantity in one carton, and some in another for the same shoe. This causes us problems because when we send it back to the ERP, it sends for example 4 lines, when there's only 3 lines on the order.

I've looked at this article on grouping but i'm getting so lost! Basically all i want to do is group it by article, so i can sum the quantity and keep it to the same line.

I tried using this tutorial - https://www.codeproject.com/Articles/1849/Grouping-XML-using-XSLT-2

All I want to do is reproduce that output but with article 261087750000 appearing just once, with quantity 66, rather than twice with 48 and 18.

I tried this in the for-each, but it returns nothing -

<xsl:for-each select="//dispatch[generate-id(.) = generate- 
id(key('keyArticle', Carton/CartonDetails/ArticleNumber)[1])]">
<xsl:variable name="lngArticle"><xsl:value-of 
select="Carton/CartonDetails/ArticleNumber" />
</xsl:variable>
<xsl:variable name="lstCarton" 
select="//Carton[Carton/CartonDetails/ArticleNumber=$lngArticle]" />

Actual XML here -

<?xml version="1.0" encoding="UTF-8"?>
<Dispatches>
 <dispatch>
 <orderNo>4703368395</orderNo>
 <CartonQty>84</CartonQty>
 <Carton>
  <DispDate>20190613</DispDate>
  <CartonDetails>
   <LineNumber>1</LineNumber>                                  
   <ArticleNumber>261087750000</ArticleNumber>
   <Quantity>48</Quantity>
  </CartonDetails>
  <CartonDetails>
   <LineNumber>2</LineNumber>
   <ArticleNumber>261135720000</ArticleNumber>
   <Quantity>12</Quantity>
  </CartonDetails>
 </Carton>
 <Carton>
  <BoxNo>0920000075</BoxNo>
  <DispDate>20190613</DispDate>
  <CartonDetails>
   <LineNumber>1</LineNumber>
   <ArticleNumber>261087750000</ArticleNumber>
   <Quantity>18</Quantity>
   </CartonDetails>
   <CartonDetails>
   <LineNumber>2</LineNumber>
   <ArticleNumber>261087840000</ArticleNumber>
   <Quantity>6</Quantity>
   </CartonDetails>
  </Carton>
</dispatch>

Expected result would be -

<CartonDetails>
  <LineNumber>1</LineNumber>                                  
  <ArticleNumber>261087750000</ArticleNumber>
  <Quantity>66</Quantity>
</CartonDetails>

标签: xmlxslt

解决方案


考虑跨多个返回具有不同ArticleNumber的CartonDetails的模板工作。然后对键的数量求和。

<?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" omit-xml-declaration="no" indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:key name="keyArticle" match="CartonDetails" use="ArticleNumber"/>

  <xsl:template match="/Dispatches">
      <Carton>
          <xsl:apply-templates select="dispatch/Carton"/>
      </Carton>
  </xsl:template>

  <xsl:template match="Carton">
      <xsl:apply-templates select="CartonDetails[generate-id() =
                         generate-id(key('keyArticle', ArticleNumber)[1])]"/>
  </xsl:template>

  <xsl:template match="CartonDetails">
      <xsl:copy>
          <xsl:copy-of select="LineNumber|ArticleNumber"/>
          <Quantity>
             <xsl:value-of select="sum(key('keyArticle', ArticleNumber)/Quantity)"/>
          </Quantity>
      </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

在线演示

输出

<?xml version="1.0" encoding="UTF-8"?>
<Carton>
   <CartonDetails>
      <LineNumber>1</LineNumber>
      <ArticleNumber>261087750000</ArticleNumber>
      <Quantity>66</Quantity>
   </CartonDetails>
   <CartonDetails>
      <LineNumber>2</LineNumber>
      <ArticleNumber>261135720000</ArticleNumber>
      <Quantity>12</Quantity>
   </CartonDetails>
   <CartonDetails>
      <LineNumber>2</LineNumber>
      <ArticleNumber>261087840000</ArticleNumber>
      <Quantity>6</Quantity>
   </CartonDetails>
</Carton>

推荐阅读