3

I have the source collection as below.

<SourceCollection>
<Row1>
 <Col1>Store1</Col1>
 <Col2>Med1</Col2>
    <Col3>Val1</Col3>
</Row1>
<Row2>
 <Col1>Store1</Col1>
    <Col2>Med1</Col2>
      <Col3>Val2</Col3>
</Row2>
<Row3>
<Col1>Store1</Col1>
    <Col2>Med2</Col2>
        <Col3>Val2</Col3>
</Row3>
<Row4>
<Col1>Store2</Col1>
     <Col2>Med1</Col2>
        <Col3>Val4</Col3>
</Row4>
</SourceCollection>

I want the target collection as below with minimal usage of for each.

<TargetCollection>
<Store value=Store1>
 <Dim value=Med1>
              <DimCode>Val1</DimCode>
              <DimCode>Val2</DimCode>
     </Dim>
     <Dim value=Med2>
              <DimCode>Val3</DimCode>
     </Dim>
</Store>
<Store value=Store2>
     <Dim value=Med1>
              <DimCode>Val4</DimCode>
     </Dim>
</Store>
</TargetCollection>  `

In my initial design I used 3 for-each loops on the same source collection to form the target xml as required. But,the source collection contains millions of rows, which is making my transformation to traverse the whole list (Rows)to the power of 3 times, which is hitting the system performance. Please let me know any ideas to avoid this.

1 Answers1

2

Generally, using xsl:key can help speed up transforms. Try something like this:

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

    <xsl:key name="Col1" match="Col1" use="."/>
    <xsl:key name="Col2byCol1" match="Col2" use="concat(../Col1, '-', .)"/>
    <xsl:key name="Col3byCol1andCol2" 
                  match="Col3" use="concat(../Col1, '-', ../Col2, '-', .)"/>

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

    <xsl:template match="SourceCollection">
        <TargetCollection>
            <xsl:apply-templates 
                    select="*/Col1[generate-id() = 
                                   generate-id(key(local-name(), .)[1])]"/>
        </TargetCollection>
    </xsl:template>    

    <xsl:template match="Col1">
        <xsl:variable name="Column1" select="."/>
        <Store value="{.}">
            <xsl:apply-templates select="../../*/Col2[generate-id() = 
                generate-id(key('Col2byCol1', concat($Column1, '-' ,.))[1])]"/>
        </Store>
    </xsl:template>

    <xsl:template match="Col2">
        <xsl:variable name="Column1" select="../Col1"/>
        <xsl:variable name="Column2" select="."/>

        <Dim value="{.}">
            <xsl:apply-templates 
                   select="../../*[Col2=$Column2]/Col3[generate-id() = 
                          generate-id(key('Col3byCol1andCol2', 
                                   concat($Column1, '-', $Column2, '-',.)))]"/>
        </Dim>
    </xsl:template>

    <xsl:template match="Col3">
        <DimCode value="{.}">
            <xsl:apply-templates />
        </DimCode>
    </xsl:template>

</xsl:stylesheet>
Mads Hansen
  • 63,927
  • 12
  • 112
  • 147