Reputation: 49
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>
Upvotes: 0
Views: 771
Reputation: 22443
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>
Upvotes: 2