Search code examples
xmlxsltparam

Vary XSLT transformation per input parameter iteration number


I have posted my source XML and target XML and I need help in transforming it using XSLT. I am trying to split my source XML collection into different target XML documents. I would need to pass in the iteration number at runtime into XSLT.

Source XML:


<sou:rElement xmlns:sou="source.sample.com">
 <sou:Header>
    <sou:Elem1>SampleElementHeader</sou:Elem1>
 </sou:Header>
 <sou:Body>
     <sou:Elem2>
      <sou:Elem3>
          <sou:ElemCollection>
             <sou:Elements>
                    <sou:data>SomeData</sou:data>
             </sou:Elements>
             <sou:Elements>
                    <sou:data>SomeData1</sou:data>
             </sou:Elements>
             <sou:Elements>
                    <sou:data>SomeData2</sou:data>
             </sou:Elements>
             <sou:Elements>
                    <sou:data>SomeData3</sou:data>
             </sou:Elements> 
          </sou:ElemCollection>
      </sou:Elem3>
     </sou:Elem2>
 </sou:Body>
</sou:rElement>

Target XML:


First Iteration:

 <sou:rElement xmlns:sou="source.sample.com">
 <sou:Body>
     <sou:Elem2>
      <sou:Elem3>
          <sou:ElemCollection>
             <sou:Elements>
                    <sou:data>SomeData</sou:data>
             </sou:Elements>
          </sou:ElemCollection>
      <sou:Elem3>
     <sou:Elem2>
 </sou:Body>
</sou:rElement>

Second Iteration:

 <sou:rElement xmlns:sou="source.sample.com">
 <sou:Body>
     <sou:Elem2>
      <sou:Elem3>
          <sou:ElemCollection>
             <sou:Elements>
                    <sou:data>SomeData1</sou:data>
             </sou:Elements>
          </sou:ElemCollection>
      <sou:Elem3>
     <sou:Elem2>
 </sou:Body>
</sou:rElement>

Third Iteration:

 <sou:rElement xmlns:sou="source.sample.com">
 <sou:Body>
     <sou:Elem2>
      <sou:Elem3>
          <sou:ElemCollection>
             <sou:Elements>
                    <sou:data>SomeData2</sou:data>
             </sou:Elements>
          </sou:ElemCollection>
      <sou:Elem3>
     <sou:Elem2>
 </sou:Body>
</sou:rElement>

Fourth Iteration:

 <sou:rElement xmlns:sou="source.sample.com">
 <sou:Body>
     <sou:Elem2>
      <sou:Elem3>
          <sou:ElemCollection>
             <sou:Elements>
                    <sou:data>SomeData3</sou:data>
             </sou:Elements>
          </sou:ElemCollection>
      <sou:Elem3>
     <sou:Elem2>
 </sou:Body>
</sou:rElement>


Solution

  • The following XSLT:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="1.0"
                    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                    xmlns:sou="source.sample.com">
    
      <xsl:param name="iteration" select="1"/>
    
      <xsl:template match="@*|node()">
        <xsl:copy>
          <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
      </xsl:template>
    
      <xsl:template match="sou:Header"/>
    
      <xsl:template match="sou:Elements">
        <xsl:if test="count(preceding-sibling::sou:Elements) + 1 = $iteration">
          <xsl:copy>
            <xsl:apply-templates/>
          </xsl:copy>
        </xsl:if>
      </xsl:template>
    </xsl:stylesheet>
    

    Applied to the following input XML document:

    <?xml version="1.0" encoding="UTF-8"?>
    <sou:rElement xmlns:sou="source.sample.com">
      <sou:Header>
        <sou:Elem1>SampleElementHeader</sou:Elem1>
      </sou:Header>
      <sou:Body>
        <sou:Elem2>
          <sou:Elem3>
            <sou:ElemCollection>
              <sou:Elements>
                <sou:data>SomeData</sou:data>
              </sou:Elements>
              <sou:Elements>
                <sou:data>SomeData1</sou:data>
              </sou:Elements>
              <sou:Elements>
                <sou:data>SomeData2</sou:data>
              </sou:Elements>
              <sou:Elements>
                <sou:data>SomeData3</sou:data>
              </sou:Elements> 
            </sou:ElemCollection>
            <sou:Elem3>
              <sou:Elem2>
              </sou:Elem2>
            </sou:Elem3>
          </sou:Elem3>
        </sou:Elem2>
      </sou:Body>
    </sou:rElement>
    

    Will yield the following output XML when iteration is set to 1:

    <?xml version="1.0" encoding="UTF-8"?>
    <sou:rElement xmlns:sou="source.sample.com">
      <sou:Body>
        <sou:Elem2>
          <sou:Elem3>
            <sou:ElemCollection>
              <sou:Elements>
                <sou:data>SomeData</sou:data>
              </sou:Elements>
            </sou:ElemCollection>
            <sou:Elem3>
              <sou:Elem2>
              </sou:Elem2>
            </sou:Elem3>
          </sou:Elem3>
        </sou:Elem2>
      </sou:Body>
    </sou:rElement>
    

    And the desired output XML when iteration is set to 2 through 4 as well.