Home > Software design >  Transform XML by XSLT - group by child
Transform XML by XSLT - group by child

Time:02-03

Hi guys can you please help me with xslt template ? I look for some similar problems by search on this site but no one works for me as i expect. I need the as primary group key.

Input file:

<?xml version="1.0" encoding="utf-8"?>
<S5Data>
  <ZasobaList>
    <Zasoba ObjectName="Zasoba" ObjectType="Object" ID="23544052-c0c9-435c-903d-3874e26ba260">
      <Group ID="36de4745-a76f-4c5f-b80e-064a35bc96fc" Kod="GRD2" />
      <Kod>P046</Kod>
      <Detaily ObjectName="ZasobaDetail" ObjectType="List">
        <ZasobaDetail ObjectName="ZasobaDetail" ObjectType="Object" ID="233d8125-3876-4a06-9299-b3e7dfd065e4">
          <Mnozstvi>2087.6000</Mnozstvi>
        </ZasobaDetail>
      </Detaily>
    </Zasoba>
    <Zasoba ObjectName="Zasoba" ObjectType="Object" ID="31287142-763e-42b5-b01e-7034671fe4b6">
      <Group ID="a2495f5f-0bc7-4c66-a36d-8d40980d8ce7" Kod="Nezaradené" />
      <Kod>P046</Kod>
      <Detaily ObjectName="ZasobaDetail" ObjectType="List">
        <ZasobaDetail ObjectName="ZasobaDetail" ObjectType="Object" ID="eae6ed21-fb14-4f55-8c7b-b4d69b67142c">
          <Mnozstvi>32847.2000</Mnozstvi>
        </ZasobaDetail>
      </Detaily>
    </Zasoba>
    <Zasoba ObjectName="Zasoba" ObjectType="Object" ID="9e1c0e68-1c49-451b-aa7a-aa2765114d45">
      <Group ID="d35d96c8-d7b8-4e9b-a6cb-f511bb7486ae" Kod="4E" />
      <Kod>RZP06</Kod>
      <Detaily ObjectName="ZasobaDetail" ObjectType="List">
        <ZasobaDetail ObjectName="ZasobaDetail" ObjectType="Object" ID="d9a3343d-af50-4bb6-aa0a-147c5fdddd20">
          <Mnozstvi>2.0000</Mnozstvi>
        </ZasobaDetail>
      </Detaily>
    </Zasoba>
    <Zasoba ObjectName="Zasoba" ObjectType="Object" ID="c24ed8ff-86d5-4b7b-9440-1b619fdf77f4">
      <Group ID="a4ca53f8-3ee4-49a2-865e-71045390c3c5" Kod="4E" />
      <Kod>RZP06</Kod>
      <Detaily ObjectName="ZasobaDetail" ObjectType="List">
        <ZasobaDetail ObjectName="ZasobaDetail" ObjectType="Object" ID="e00e71e9-4a1d-4863-b26c-854db8d884ff">
          <Mnozstvi>0.0000</Mnozstvi>
        </ZasobaDetail>
      </Detaily>
    </Zasoba>
    <Zasoba ObjectName="Zasoba" ObjectType="Object" ID="0cb69665-9405-466a-b4ce-433e78b9e7ba">
      <Group ID="16d08933-6aac-455e-a256-a892901e03b9" Kod="4E" />
      <Kod>RZP06</Kod>
      <Detaily ObjectName="ZasobaDetail" ObjectType="List" />
    </Zasoba>
    <Zasoba ObjectName="Zasoba" ObjectType="Object" ID="a7c09308-b399-4aac-9839-a58365cdc355">
      <Group ID="3aa22f50-0076-41bd-8f9f-fbc91b2f71f5" Kod="Nezaradené" />
      <Kod>RZP06</Kod>
      <Detaily ObjectName="ZasobaDetail" ObjectType="List">
        <ZasobaDetail ObjectName="ZasobaDetail" ObjectType="Object" ID="e9b02461-78d1-4342-bfe5-80c4ff1273f6">
          <Mnozstvi>0.0000</Mnozstvi>
        </ZasobaDetail>
      </Detaily>
    </Zasoba>
  </ZasobaList>
</S5Data>

I need this format:

<?xml version="1.0" encoding="utf-8"?>
<S5Data>
  <ZasobaList>
    <Kod>P046</Kod>
    <Stav>2087.6000</Stav>
    <Stav>32847.2000</Stav>
    <Kod>RZP06</Kod>
    <Stav>2.0000</Stav>
    <Stav>0.0000</Stav>
    <Stav></Stav>
    <Stav>0.0000</Stav>
  </ZasobaList>
</S5Data>
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
   <!-- Identity transform -->
   <xsl:template match="@* | node()">
      <xsl:copy>
         <xsl:apply-templates select="@* | node()"/>
      </xsl:copy>
   </xsl:template>




<xsl:template match="Zasoba">
           <xsl:element name = "Kod">
          <xsl:value-of select="Kod" />  
                    </xsl:element>
            <xsl:element name = "Stav">
    <xsl:value-of select ="Detaily"/>
            </xsl:element>
   </xsl:template>
   </xsl:stylesheet>

Result:

<?xml version="1.0" encoding="utf-8"?>
<S5Data>
  <ZasobaList>
    <Kod>P046</Kod>
    <Stav>2087.6000</Stav>
    <Kod>P046</Kod>
    <Stav>32847.2000</Stav>
    <Kod>RZP06</Kod>
    <Stav>2.0000</Stav>
    <Kod>RZP06</Kod>
    <Stav>0.0000</Stav>
    <Kod>RZP06</Kod>
    <Stav></Stav>
    <Kod>RZP06</Kod>
    <Stav>0.0000</Stav>
  </ZasobaList>
</S5Data>

I manage my transform xslt template but it missing foreach or something to group by child node ? Thanks for help, sorry for basic question but i started learning xsl yesterday.

CodePudding user response:

if it has to be xslt 1.0 then this does it

<?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:key name="lookup" match="/S5Data/ZasobaList/Zasoba" use="Kod" />
    
    <xsl:template match="/">
        <S5Data>
            <ZasobaList>
                <xsl:for-each select="S5Data/ZasobaList/Zasoba[generate-id(.) = generate-id(key('lookup',Kod)[1])]">
                    <Kod>
                        <xsl:value-of select="Kod"/>
                    </Kod>
                    <xsl:for-each select="key('lookup',Kod)">
                        <xsl:for-each select="Detaily/ZasobaDetail/Mnozstvi">
                            <Stav>
                                <xsl:value-of select="."/>
                            </Stav>
                        </xsl:for-each>
                    </xsl:for-each>
                    <Sum>
                        <xsl:value-of select="sum(key('lookup',Kod)/Detaily/ZasobaDetail/Mnozstvi)"/>
                    </Sum>
                </xsl:for-each>
            </ZasobaList>
        </S5Data>
    </xsl:template>
</xsl:stylesheet>

I've tweaked the 'key' based on micheal.Hor257k feedback, and your sum issue.

this now outputs

<?xml version="1.0" encoding="utf-8"?>
<S5Data>
  <ZasobaList>
    <Kod>P046</Kod>
    <Stav>2087.6000</Stav>
    <Stav>32847.2000</Stav>
    <Sum>34934.799999999995</Sum>
    <Kod>RZP06</Kod>
    <Stav>2.0000</Stav>
    <Stav>0.0000</Stav>
    <Stav>0.0000</Stav>
    <Sum>2</Sum>
  </ZasobaList>
</S5Data>

(welcome to the world of floating point maths)

  • Related