This discussion is archived
2 Replies Latest reply: May 14, 2013 3:35 PM by oracleistheway RSS

Problem with grouping Elements

oracleistheway Newbie
Currently Being Moderated
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 Guru
    Currently Being Moderated
    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 Newbie
    Currently Being Moderated
    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.

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points