Home > Software engineering >  XSLT grouping / merging - two or more different nodes into one
XSLT grouping / merging - two or more different nodes into one

Time:04-24

Struggling with an xslt transformation.

I have two (or more) identical <A_OutbDeliveryHeader> nodes, except for the <to_DeliveryDocumentItem> part.

<to_DeliveryDocumentItem>
      <A_OutbDeliveryItemType>
      ...
      </A_OutbDeliveryItemType>
</to_DeliveryDocumentItem>

As a result, I would like have one single <A_OutbDeliveryHeader> node, with multiple entries in <to_DeliveryDocumentItem>.

<A_OutbDeliveryHeader>
  <A_OutbDeliveryHeaderType>
    <DeliveryDocumentType>LF</DeliveryDocumentType>
    <to_DeliveryDocumentText>
    ...
    </to_DeliveryDocumentText>
    ...
    <to_DeliveryDocumentItem>
      <A_OutbDeliveryItemType>
      ...
      </A_OutbDeliveryItemType>
      <A_OutbDeliveryItemType>
      ...
      </A_OutbDeliveryItemType>
    </to_DeliveryDocumentItem>
  </A_OutbDeliveryHeaderType>
</A_OutbDeliveryHeader>

What would be the best way to get started? Group-by? I don't have any keys though. Note : I can use XSLT 2.0 or 3.0.

Complete example XML

<?xml version="1.0" encoding="UTF-8"?>
<A_OutbDeliveryHeader>
  <A_OutbDeliveryHeaderType>
    <DeliveryDocumentType>LF</DeliveryDocumentType>
    <to_DeliveryDocumentText>
      <A_OutbDeliveryHeaderTextType>
        <DeliveryDocument>800005120</DeliveryDocument>
        <TextElementText>Lorem Ipsum</TextElementText>
      </A_OutbDeliveryHeaderTextType>
    </to_DeliveryDocumentText>
    <to_DeliveryDocumentItem>
      <A_OutbDeliveryItemType>
        <DeliveryDocumentItem>000010</DeliveryDocumentItem>
        <Warehouse>103</Warehouse>
        <ItemWeightUnit>KG</ItemWeightUnit>
        <ActualDeliveryQuantity>3.000</ActualDeliveryQuantity>
        <ReferenceSDDocumentItem>000010</ReferenceSDDocumentItem>
        <Plant>1003</Plant>
      </A_OutbDeliveryItemType>
    </to_DeliveryDocumentItem>
  </A_OutbDeliveryHeaderType>
  <A_OutbDeliveryHeaderType>
    <DeliveryDocumentType>LF</DeliveryDocumentType>
    <to_DeliveryDocumentText>
      <A_OutbDeliveryHeaderTextType>
        <DeliveryDocument>800005120</DeliveryDocument>
        <TextElementText>Lorem Ipsum</TextElementText>
      </A_OutbDeliveryHeaderTextType>
    </to_DeliveryDocumentText>
    <to_DeliveryDocumentItem>
      <A_OutbDeliveryItemType>
        <DeliveryDocumentItem>000011</DeliveryDocumentItem>
        <Warehouse>104</Warehouse>
        <ItemWeightUnit>PC</ItemWeightUnit>
        <ActualDeliveryQuantity>1.000</ActualDeliveryQuantity>
        <ReferenceSDDocument>4858</ReferenceSDDocument>
      </A_OutbDeliveryItemType>
    </to_DeliveryDocumentItem>
  </A_OutbDeliveryHeaderType>
</A_OutbDeliveryHeader>

Edit : my XSLT (I can use XSLT 2.0 or 3.0) so far, seems to do the trick.

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

    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="//A_OutbDeliveryHeader">
        <xsl:copy>
            <xsl:for-each-group select="A_OutbDeliveryHeaderType" group-by="''">
                <xsl:apply-templates select="@* | node()[not(self::to_DeliveryDocumentItem)]" />
                <to_DeliveryDocumentItem>
                  <xsl:apply-templates select="current-group()/to_DeliveryDocumentItem/A_OutbDeliveryItemType" />
                </to_DeliveryDocumentItem>
            </xsl:for-each-group>
        </xsl:copy>

    </xsl:template>

</xsl:stylesheet>

CodePudding user response:

It appears you don't need grouping, just

<xsl:template match="A_OutbDeliveryHeader">
    <xsl:copy>
        <xsl:copy-of select="A_OutbDeliveryHeaderType[1]/(* except to_DeliveryDocumentItem)"/>
        <to_DeliveryDocumentItem>
              <xsl:copy-of select="A_OutbDeliveryHeaderType/to_DeliveryDocumentItem/A_OutbDeliveryItemType"/>
        </to_DeliveryDocumentItem>
    </xsl:copy>
</xsl:template>
  • Related