0

I need to solve a groping problem in my xsl; I have to group the input xml based on , and . If any of these data is not same then create new tag and copy the respective inside that. If you check my xslt i am able to do the grouping by but not sure how to incorporate the same logic for and . I am not sure if i explained the problem very well but if u see the "needed output" section it would be more easy to understand what I want. Thanks in advance for your help.

Input:

<?xml version="1.0" encoding="UTF-8"?>
<BC>
    <SO>
        <plantCode>xyz</plantCode>
        <airportofloading>US</airportofloading>
        <airportofunloading>UK</airportofunloading>
                  <package>1</package>
                  ....
    </SO>
    <SO>
        <plantCode>xyz</plantCode>
        <airportofloading>US</airportofloading>
        <airportofunloading>UK</airportofunloading>
                  <package>2</package>
                  ...
    </SO>
    <SO>
        <plantCode>abc</plantCode>
        <airportofloading>US</airportofloading>
        <airportofunloading>UK</airportofunloading>
                  <package>5</package>
                  ....
    </SO>
    <SO>
        <plantCode>abc</plantCode>
        <airportofloading>US</airportofloading>
        <airportofunloading>AB</airportofunloading>
                  <package>1</package>
                  ....
    </SO>
</BC>

Needed Output:

<?xml version="1.0" encoding="UTF-8"?>
<BC>
    <plant name="xyz">
        <SO>
            <plantCode>xyz</plantCode>
            <airportofloading>US</airportofloading>
            <airportofunloading>UK</airportofunloading>
                            <package>1</package>
                            ....
        </SO>
        <SO>
            <plantCode>xyz</plantCode>
            <airportofloading>US</airportofloading>
            <airportofunloading>UK</airportofunloading>
                            <package>2</package>
                            ....
        </SO>
    </plant>
    <plant name="abc">
        <SO>
            <plantCode>abc</plantCode>
            <airportofloading>US</airportofloading>
            <airportofunloading>UK</airportofunloading>
                            <package>5</package>
                            ....

        </SO>
    </plant>
    <plant name="abc">
        <SO>
            <plantCode>abc</plantCode>
            <airportofloading>US</airportofloading>
            <airportofunloading>AB</airportofunloading>
                            <package>1</package>
                            ....

        </SO>
    </plant>
    </BC>

My XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"     xmlns:fo="http://www.w3.org/1999/XSL/Format">
    <xsl:output method="xml"/>
    <xsl:key name="Code" match="SO" use="plantCode"/>
    <xsl:template match="BC">
        <xsl:element name="BC">
            <xsl:apply-templates select="SO[generate-id(.) = generate-id(key    ('Code', plantCode)[1])]"/>
            </xsl:element>
</xsl:template>
<xsl:template match="SO">
    <xsl:element name="plant">
        <xsl:attribute name="name"><xsl:value-of     select="plantCode"/></xsl:attribute>
            <xsl:for-each select="key('Code', plantCode)">
                <xsl:copy-of select="."/>
            </xsl:for-each>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>
Pankaj
  • 177
  • 1
  • 9

1 Answers1

1

Edit: Sorry, I see now I misunderstood your question. I belive the following is more or less what you are looking for:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:key name="code" match="SO" use="plantCode" />
  <xsl:key name="airports" match="SO" use="concat(airportofloading,' ',airportofunloading)" />
  <xsl:output indent="yes"/>
  <xsl:template match="/">
        <xsl:apply-templates />
  </xsl:template>
  <xsl:template match="BC">
        <BC>
              <xsl:for-each select="SO[generate-id(.)=generate-id(key('code',plantCode))]">
                    <xsl:variable name="thisCode" select="plantCode"/>
                    <xsl:for-each select="../SO[generate-id() = generate-id(key('airports', concat(airportofloading,' ',airportofunloading))[plantCode = $thisCode][1])]">
                          <xsl:element name="plant">
                                <xsl:attribute name="name">
                                      <xsl:value-of select="plantCode"/>
                                </xsl:attribute>
                                <xsl:for-each select="key('airports', concat(airportofloading,' ',airportofunloading))[plantCode = $thisCode]">
                                      <xsl:copy-of select="."/>
                                </xsl:for-each>
                          </xsl:element>
                    </xsl:for-each>
              </xsl:for-each>
        </BC>
  </xsl:template>

That should create one <plant> element for every triple of {plantcode, airportofloading, airportofunloading}. Said <plant> element containing all the <SO> elements for that triple. I believe that is what you wanted, or is very close to it, so you should be able to make any needed adjustments.

Kevin Cathcart
  • 9,838
  • 2
  • 36
  • 32
  • Thanks for your comment. I have gone through the code page, but not sure if i understand correctly. as I mentioned i have successfully grouped by plantCode, now i have to implement same logic for airpotofloading and airportofunloading. It would be great if you can modify my xslt or give some direction to achieve desire output. Thanks again for you help. – Pankaj Feb 28 '11 at 20:00
  • @user637711: I've completely edited by post to show XSLT that does what I believe you want. If is is still not right please let me know. – Kevin Cathcart Mar 01 '11 at 04:24
  • This is perfect. Thanks a lot for your help. I am still trying to understand the code but this is what I wanted. Thanks again. – Pankaj Mar 01 '11 at 05:46
  • @user637711: Sure. If you need more help understanding that code, may I suggest reading http://stackoverflow.com/questions/948218/xslt-3-level-grouping-on-attributes/955527#955527 which deals with a very similar question (although I did not find that post until after I wrote mine), and which includes a relatively thorough explanation of XSL Keys, which should help you understand the code. If after reading that you still have questions about my code, please let me know. Also, if you are satisfied with my answer, could you please mark it as an accepted answer? Thanks. – Kevin Cathcart Mar 01 '11 at 13:36