0
votes

I am trying to convert a nested XML structure to a Flat XML using for-each in xslt but struggling :( Below is my source and target, so any inputs using XSLT will be very appreciated.

Source XML

<LS>    
<dlu fD="2012-06-07" tD="2012-06-13">
        <ULUI uid="uid-1" fAD="2012-06-11" lAD="2012-06-11">
          <LU license="License1" count="1"/>
        </ULUI>
        <ULUI uid="uid-2" fAD="2012-06-10" lAD="2012-06-10">
          <LU license="License1" count="1"/>
        </ULUI>
        <ULUI uid="uid-3" fAD="2012-06-09" lAD="2012-06-09">
          <LU license="License1" count="1"/>
        </ULUI>
        <ULUI uid="uid-4" fAD="2012-06-07" lAD="2012-06-08">
          <LU license="License3" count="1"/>
          <LU license="License4" count="1"/>
        </ULUI>
        <ULUI uid="uid-5" fAD="2012-06-07" lAD="2012-06-08">
          <LU license="License1" count="1"/>
          <LU license="License5" count="1"/>
        </ULUI>
      </dlu>
      <dlu fD="2012-06-14" tD="2012-06-20">
        <ULUI uid="uid-1" fAD="2012-06-14" lAD="2012-06-14">
          <LU license="License1" count="1"/>
        </ULUI>
        <ULUI uid="uid-2" fAD="2012-06-15" lAD="2012-06-20">
          <LU license="License2" count="1"/>
          <LU license="License4" count="1"/>
        </ULUI>
        <ULUI uid="uid-3" fAD="2012-06-16" lAD="2012-06-19">
          <LU license="License1" count="1"/>
          <LU license="License5" count="1"/>
        </ULUI>
        <ULUI uid="uid-4" fAD="2012-06-17" lAD="2012-06-18">
          <LU license="License1" count="1"/>
          <LU license="License3" count="1"/>
        </ULUI>
        <ULUI uid="uid-5" fAD="2012-06-17" lAD="2012-06-18">
          <LU license="License7" count="1"/>
          <LU license="License9" count="1"/>
        </ULUI>
    </dlu>
</LS>

Target XML

<FDLU>
<LU>
<LD_FR_DT>2012-06-07</LD_FR_DT
<LD_TO_DT>2012-06-13</LD_TO_DT>
<LU_UID>uid-1</LU_UID>  
<LU_FA_DT>2012-06-11</LU_FA_DT>
<LU_LA_DT>2012-06-11</LU_LA_DT>
<LU_LICENSE>License1</LU_LICENSE>
<LU_COUNT>1</LU_COUNT>
</LU>
<LU>
<LD_FR_DT>2012-06-07</LD_FR_DT
<LD_TO_DT>2012-06-13</LD_TO_DT>
<LU_UID>uid-2</LU_UID>  
<LU_FA_DT>2012-06-10</LU_FA_DT>
<LU_LA_DT>2012-06-10</LU_LA_DT>
<LU_LICENSE>License1</LU_LICENSE>
<LU_COUNT>1</LU_COUNT>
</LU>
<LU>
<LD_FR_DT>2012-06-07</LD_FR_DT
<LD_TO_DT>2012-06-13</LD_TO_DT>
<LU_UID>uid-4</LU_UID>  
<LU_FA_DT>2012-06-07</LU_FA_DT>
<LU_LA_DT>2012-06-08</LU_LA_DT>
<LU_LICENSE>License3</LU_LICENSE>
<LU_COUNT>1</LU_COUNT>
</LU>
<LU>
<LD_FR_DT>2012-06-07</LD_FR_DT
<LD_TO_DT>2012-06-13</LD_TO_DT>
<LU_UID>uid-4</LU_UID>  
<LU_FA_DT>2012-06-07</LU_FA_DT>
<LU_LA_DT>2012-06-08</LU_LA_DT>
<LU_LICENSE>License4</LU_LICENSE>
<LU_COUNT>1</LU_COUNT>
</LU>
<LU>
<LD_FR_DT>2012-06-07</LD_FR_DT
<LD_TO_DT>2012-06-13</LD_TO_DT>
<LU_UID>uid-5</LU_UID>  
<LU_FA_DT>2012-06-07</LU_FA_DT>
<LU_LA_DT>2012-06-08</LU_LA_DT>
<LU_LICENSE>License1</LU_LICENSE>
<LU_COUNT>1</LU_COUNT>
</LU>
<LU>
<LD_FR_DT>2012-06-07</LD_FR_DT
<LD_TO_DT>2012-06-13</LD_TO_DT>
<LU_UID>uid-5</LU_UID>  
<LU_FA_DT>2012-06-07</LU_FA_DT>
<LU_LA_DT>2012-06-08</LU_LA_DT>
<LU_LICENSE>License5</LU_LICENSE>
<LU_COUNT>1</LU_COUNT>
</LU>
<LD_FR_DT>2012-06-14</LD_FR_DT
<LD_TO_DT>2012-06-20</LD_TO_DT>
<LU_UID>uid-1</LU_UID>  
<LU_FA_DT>2012-06-14</LU_FA_DT>
<LU_LA_DT>2012-06-14</LU_LA_DT>
<LU_LICENSE>License1</LU_LICENSE>
<LU_COUNT>1</LU_COUNT>
</LU>
.....
</FDLU>

So basically I need a flat row per LU from source, but my ULUI & DLU are also unbounded so they can appear more than once. I am looking for a solution in xslt 1.0 or 2.0 version. I started with for-each LU and then tried to proceed, but I'm not able to handle ULUI and DLU multi occurrence and values for them simply end up in one line.

My effort in progress

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xml="http://www.w3.org/XML/1998/namespace" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output encoding="UTF-8" indent="yes" method="xml"/>
     <xsl:variable name="srcDoc1" select="bpws:getVariableData('XMLVar')"/>
   <xsl:template match="/">
      <xsl:element name="FDLU" namespace="">
<!--         <xsl:for-each select="$srcDoc1/LS/DLU"> -->
<!--            <xsl:for-each select="/DLU/ULUI"> -->
                <xsl:for-each select="$srcDoc1/LS/DLU/ULUI/LU">
                       <xsl:element name="LD_FR_DT" namespace="">
                            <xsl:value-of select="$srcDoc1/LS/DLU/@fD"/>
                         </xsl:element>
                       <xsl:element name="LD_TO_DT" namespace="">
                            <xsl:value-of select="$srcDoc1/LS/DLU/@tD"/>
                         </xsl:element>
                       <xsl:element name="LU_UID" namespace="">
                            <xsl:value-of select="$srcDoc1/LS/DLU/ULUI/@uid"/>
                         </xsl:element>
                       <xsl:element name="LU_FA_DT" namespace="">
                            <xsl:value-of select="$srcDoc1/LS/DLU/ULUI/@fAD"/>
                         </xsl:element>
                       <xsl:element name="LU_LA_DT" namespace="">
                            <xsl:value-of select="$srcDoc1/LS/DLU/ULUI/@lAD"/>
                         </xsl:element>
                       <xsl:element name="LU_LICENSE" namespace="">
                            <xsl:value-of select="@license"/>
                         </xsl:element>
                       <xsl:element name="LU_COUNT" namespace="">
                            <xsl:value-of select="@count"/>
                         </xsl:element>
                      </xsl:element>
<!--                    </xsl:for-each> -->
<!--              </xsl:for-each> -->
           </xsl:for-each>
        </xsl:element>
     </xsl:template>
  </xsl:stylesheet>
1
Why don't you show us what you have so far. - Matthew Whited
Also, is there a root on your XML or is that two XML documents? - Matthew Whited
Sorry, i missed the root, i added that in source XML. It is one single XML. Also added what i have been trying, may be i am in the wrong direction. Thanks - Zooming Rocket

1 Answers

2
votes

I assume this is the correct mapping... this can easily be done with applytemplates as well.

Note: Your example XML is a fragment so I wrapped it with an outer element for testing.

<xsl:stylesheet
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:msxsl="urn:schemas-microsoft-com:xslt"
  exclude-result-prefixes="msxsl"
>
  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="/">
    <FDUL>
      <xsl:for-each select="//LU">
        <LU>
          <LD_FR_DT>
            <xsl:value-of select="../../@fD"/>
          </LD_FR_DT>
          <LD_TO_DT>
            <xsl:value-of select="../../@tD"/>
          </LD_TO_DT>
          <LU_UID>
            <xsl:value-of select="../@uid"/>
          </LU_UID>
          <LU_FA_DT>
            <xsl:value-of select="../@fAD"/>
          </LU_FA_DT>
          <LU_LA_DT>
            <xsl:value-of select="../@lAD"/>
          </LU_LA_DT>
          <LU_LICENSE>
            <xsl:value-of select="@license"/>
          </LU_LICENSE>
          <LU_COUNT>
            <xsl:value-of select="@count"/>
          </LU_COUNT>
        </LU>
      </xsl:for-each>
    </FDUL>
  </xsl:template>
</xsl:stylesheet>