user6341824
user6341824

Reputation: 21

how to combine elements in multiple rows using a repeating element

Below is my Input xml and I want to use xslt 1.0 to transform into below specified xml.

Element ref needs to be used as key to merge and create the array in the output Input xml :

<Input>
     <row>
        <Name>ABC</Name>
        <Ref>12345</Ref>
        <Status>O</Status>
         <Currency>USD</Currency>
        <Date>2016-05-16</Date>
    </row>
     <row>
        <Name>ABC</Name>
        <Ref>12345</Ref>
         <Status>O</Status>
        <Currency>AUD</Currency>
        <Date>2016-05-01</Date>
    </row>
    <row>
        <Name>XYZ</Name>
         <Ref>54321</Ref>
        <Status>O</Status>
        <Currency>AUD</Currency>
         <Date>2016-03-01</Date>
    </row>
    <row>
        <Name>XYZ</Name>
         <Ref>54321</Ref>
         <Status>O</Status>
         <Currency>USD</Currency>
        <Date>2016-05-01</Date>
    </row>
</Input>

Output Xml: using the ref element in the request the there will be only two row elements in the output xml, but the values that are different are clubbed in a another sub node.

<Output>
    <row>
        <Name>ABC</Name>
         <Ref>12345</Ref>
        <Status>O</Status>
         <Details>
                 <Detail>
                    <Currency>USD</Currency>
                     <Date>2016-05-16</Date>
                </Detail>
                 <Detail>
                    <Currency>AUD</Currency>
                    <Date>2016-05-01</Date>
                 </Detail>
            </Details>
     </row>
     <row>
        <Name>XYZ</Name>
        <Ref>54321</Ref>
         <Status>O</Status>
         <Details>
                 <Detail>
                     <Currency>AUD</Currency>
                      <Date>2016-03-01</Date>
                 </Detail>
                 <Detail>
                     <Currency>USD</Currency>
                    <Date>2016-05-01</Date>
                </Detail>
         </Details>
     </row>
</Output>

Any help ?

Tried using the below xslt , but the if condition isn't working

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<xsl:output method="xml" version="1.0"/>
<xsl:template match="/">
<xsl:element name="Output">
    <xsl:apply-templates select="Input"/>
</xsl:element>  
</xsl:template>
<xsl:template match="Input">
<xsl:for-each select="row">
    <xsl:if test="(following-sibling::Ref = /Ref)">
      <xsl:element name="row">
           <xsl:element name="Name">
                <xsl:value-of select="Name" />
            </xsl:element>
            <xsl:element name="Ref">
                <xsl:value-of select="Ref" />
            </xsl:element>
            <xsl:element name="Status">
                <xsl:value-of select="Status" />
            </xsl:element>
            <xsl:element name="Details"> 
               <xsl:element name="Detail"> 
                <xsl:element name="Currency">
                    <xsl:value-of select="Currency" />
                </xsl:element>
                <xsl:element name="Date">
                    <xsl:value-of select="Date" />
                </xsl:element>
               </xsl:element>
            </xsl:element>
        </xsl:element>
        </xsl:if>   
    </xsl:for-each> 
</xsl:template>
</xsl:stylesheet>

Upvotes: 2

Views: 1985

Answers (1)

Dimitre Novatchev
Dimitre Novatchev

Reputation: 243469

This transformation:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:key name="kRowByRefNameStat" match="row" use="concat(Name, '|', Ref, '|', Status)"/>

  <xsl:template match="/*">
    <Output>
      <xsl:apply-templates select=
      "row[generate-id()
      =
       generate-id(key('kRowByRefNameStat', 
                        concat(Name, '|', Ref, '|', Status))[1])]"/>
    </Output>
  </xsl:template>
  <xsl:template match="row">
    <row>
      <xsl:copy-of select="Name | Ref | Status"/>
      <Details>
          <xsl:apply-templates mode="inGroup" select=
          "key('kRowByRefNameStat', concat(Name, '|', Ref, '|', Status))"/>
        </Details>
    </row>
  </xsl:template>
  <xsl:template match="row" mode="inGroup">
    <Detail><xsl:copy-of select="Currency | Date"/></Detail>
  </xsl:template>
</xsl:stylesheet>

when applied on the provided XML document:

<Input>
     <row>
        <Name>ABC</Name>
        <Ref>12345</Ref>
        <Status>O</Status>
         <Currency>USD</Currency>
        <Date>2016-05-16</Date>
    </row>
     <row>
        <Name>ABC</Name>
        <Ref>12345</Ref>
         <Status>O</Status>
        <Currency>AUD</Currency>
        <Date>2016-05-01</Date>
    </row>
    <row>
        <Name>XYZ</Name>
         <Ref>54321</Ref>
        <Status>O</Status>
        <Currency>AUD</Currency>
         <Date>2016-03-01</Date>
    </row>
    <row>
        <Name>XYZ</Name>
         <Ref>54321</Ref>
         <Status>O</Status>
         <Currency>USD</Currency>
        <Date>2016-05-01</Date>
    </row>
</Input>

produces the wanted, correct result:

<Output>
   <row>
      <Name>ABC</Name>
      <Ref>12345</Ref>
      <Status>O</Status>
      <Details>
         <Detail>
            <Currency>USD</Currency>
            <Date>2016-05-16</Date>
         </Detail>
         <Detail>
            <Currency>AUD</Currency>
            <Date>2016-05-01</Date>
         </Detail>
      </Details>
   </row>
   <row>
      <Name>XYZ</Name>
      <Ref>54321</Ref>
      <Status>O</Status>
      <Details>
         <Detail>
            <Currency>AUD</Currency>
            <Date>2016-03-01</Date>
         </Detail>
         <Detail>
            <Currency>USD</Currency>
            <Date>2016-05-01</Date>
         </Detail>
      </Details>
   </row>
</Output>

Explanation:

  1. Muenchian grouping using composite-keys

  2. Modes

Upvotes: 2

Related Questions