开发者

grouping in xslt 1.0

开发者 https://www.devze.com 2023-02-14 02:18 出处:网络
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 newtag and copy the respectiveinside that. If you check my xslt

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开发者_C百科>
            <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>


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号