2 Replies Latest reply: May 14, 2013 5:35 PM by oracleistheway RSS

    Problem with grouping Elements

    oracleistheway
      Hi everyone. Thank you for taking the time to look over my examples.

      I am having trouble grouping the elements with XSL.

      Input XML:
      <Country>
      <info enum="CTRY" name="United Sates of America" total-states="50" />
      <info enum="ST" name="New York" population="8,244,910"/>
      <info enum="ST" name="Chicago" population="2,707,120"/>
      <info enum="CTRY" name="Germany" total-states="16"/>
      <info enum="ST" name="Berlin" population="3,469,910"/>
      <info enum="ST" name="Brandenburg" population="2,500,000"/>
      </Country>
      ------------------------------------------------------------------------------------------
      My XSL:
      <xsl:template match="/">
      <Country>
      <xsl:for-each select="Country/info">
      <xsl:if test="@enum='CTRY'">
      <CountryInfo>
      <name>Country Name: <xsl:value-of select="@name"/></name>
      <districts><xsl:value-of select="@total-states"></xsl:value-of></districts>
      <xsl:for-each select="/Country/info">
      <xsl:if test="@enum='ST'">
      <state>
      <stateName>State Name: <xsl:value-of select="@name"/></stateName>
      <statePop>State Population: <xsl:value-of select="@population"/></statePop>
      </state>
      </xsl:if>
      </xsl:for-each>
      </CountryInfo>
      </xsl:if>
      </xsl:for-each>
      </Country>
      </xsl:template>

      My undesired result:
      <Country>
      <CountryInfo>
      <name>Country Name: United Sates of America</name>
      <districts>50</districts>
      <state>
      <stateName>State Name: New York</stateName>
      <statePop>State Population: 8,244,910</statePop>
      </state>
      <state>
      <stateName>State Name: Chicago</stateName>
      <statePop>State Population: 2,707,120</statePop>
      </state>
      <state>
      <stateName>State Name: Berlin</stateName>
      <statePop>State Population: 3,469,910</statePop>
      </state>
      <state>
      <stateName>State Name: Brandenburg</stateName>
      <statePop>State Population: 2,500,000</statePop>
      </state>
      </CountryInfo>
      <CountryInfo>
      <name>Country Name: Germany</name>
      <districts>16</districts>
      <state>
      <stateName>State Name: New York</stateName>
      <statePop>State Population: 8,244,910</statePop>
      </state>
      <state>
      <stateName>State Name: Chicago</stateName>
      <statePop>State Population: 2,707,120</statePop>
      </state>
      <state>
      <stateName>State Name: Berlin</stateName>
      <statePop>State Population: 3,469,910</statePop>
      </state>
      <state>
      <stateName>State Name: Brandenburg</stateName>
      <statePop>State Population: 2,500,000</statePop>
      </state>
      </CountryInfo>
      </Country>
      ---------------------------------------------------------------------------------------
      ++++++++++++++++++++++++++++++++++++++++++++
      My other XSL:
      <xsl:template match="/">
      <xsl:for-each-group select="Country/info" group-by="@enum">
      <xsl:for-each-group select="current-group()" group-by="@name">
      <xsl:if test="@enum='CTRY'">
      <Country>
      <CountryInfo>
      <name>Country Name: <xsl:value-of select="@name"/></name>
      <districts><xsl:value-of select="@total-states"></xsl:value-of></districts>
      <xsl:for-each-group select="/Country/info" group-by="@enum">
      <xsl:if test="@enum='ST'">
      <state>
      <stateName>State Name: <xsl:value-of select="@name"/></stateName>
      <statePop>State Population: <xsl:value-of select="@population"/></statePop>
      </state>
      </xsl:if>
      </xsl:for-each-group>
      </CountryInfo>
      </Country>
      </xsl:if>
      </xsl:for-each-group>
      </xsl:for-each-group>
      </xsl:template>

      Other undesired result:
      <Country>
      <CountryInfo>
      <name>Country Name: United Sates of America</name>
      <districts>50</districts>
      <state>
      <stateName>State Name: New York</stateName>
      <statePop>State Population: 8,244,910</statePop>
      </state>
      </CountryInfo>
      </Country>
      <Country>
      <CountryInfo>
      <name>Country Name: Germany</name>
      <districts>16</districts>
      <state>
      <stateName>State Name: New York</stateName>
      <statePop>State Population: 8,244,910</statePop>
      </state>
      </CountryInfo>
      </Country>
      +++++++++++++++++++++++++++++++++++++++++

      Desired result:
      <Country>
      <CountryInfo>
      <name>Country Name: United Sates of America</name>
      <districts>50</districts>
      <state>
      <stateName>State Name: New York</stateName>
      <statePop>State Population: 8,244,910</statePop>
      </state>
      <state>
      <stateName>State Name: Chicago</stateName>
      <statePop>State Population: 2,707,120</statePop>
      </state>
      </CountryInfo>
      <CountryInfo>
      <name>Country Name: Germany</name>
      <districts>16</districts>
      <state>
      <stateName>State Name: Berlin</stateName>
      <statePop>State Population: 3,469,910</statePop>
      </state>
      <state>
      <stateName>State Name: Brandenburg</stateName>
      <statePop>State Population: 2,500,000</statePop>
      </state>
      </CountryInfo>
      </Country>

      If possible, how can I produce my desired result given the input XML?
        • 1. Re: Problem with grouping Elements
          odie_63
          Hi,

          Since apparently you can use XSLT 2.0, here's a solution leveraging some of the grouping functionalities :
          <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
            <xsl:output method="xml" indent="yes"/>
            
            <xsl:template match="/">
              <Country>
                <xsl:for-each-group select="Country/*" group-starting-with="info[@enum='CTRY']">
                  <CountryInfo>
                    <xsl:apply-templates select="current-group()"/> 
                  </CountryInfo>
                </xsl:for-each-group>
              </Country>
            </xsl:template>
           
            <xsl:template match="info[@enum='CTRY']"> 
              <name>Country Name: <xsl:value-of select="@name"/></name>
              <districts><xsl:value-of select="@total-states"/></districts>  
            </xsl:template>
            
            <xsl:template match="info[@enum='ST']">
              <state>
                <stateName>State Name: <xsl:value-of select="@name"/></stateName>
                <statePop>State Population: <xsl:value-of select="@population"/></statePop>
              </state>
            </xsl:template>
            
          </xsl:stylesheet>
          {code}
          
          (tested with Saxon HE 9.4.0.6)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
          • 2. Re: Problem with grouping Elements
            oracleistheway
            Hi odie_63,

            I did think about splitting the processes up, but I do not know all of the functionality that XSLT offers.

            Thank you for your help.