Check for new replies
Thread Rating:
  • 43 Vote(s) - 2.67 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Grouping example in XSLT 2.0
#1
XSLT2.0 provides us with grouping facility unlike XSLT1.0 where we should use key(), or following-sibling, or preceding-sibling axis to get the expected output. These methods are fragile and not easy to code.

This simple example can be used in place of the previous example of grouping using preceding-sibling axis.(Grouping in XSLT-1.0 using preceding-sibling axis)

Let's consider the same example input:
Code:
<items>
    <item type="A">1</item>
    <item type="B">2</item>
    <item type="C">3</item>
    <item type="B">4</item>
    <item type="B">5</item>
    <item type="C">6</item>
    <item type="A">7</item>
</items>

and the expected output is to get "item"s grouped by "@type" in the following way:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<items>
   <item type="A">
      <item>1</item>
      <item>7</item>
   </item>
   <item type="B">
      <item>2</item>
      <item>4</item>
      <item>5</item>
   </item>
   <item type="C">
      <item>3</item>
      <item>6</item>
   </item>
</items>

The XSLT2.0 code to transform the input to output would be:
Code:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>
    <xsl:template match="/items">
        <items>
            <xsl:for-each-group select="item" group-by="@type">
                <item type="{current-grouping-key()}">
                    <xsl:for-each select="current-group()">
                        <item>
                            <xsl:value-of select="."/>
                        </item>
                    </xsl:for-each>
                </item>
            </xsl:for-each-group>
        </items>
    </xsl:template>
</xsl:stylesheet>

Coming to the description of this code,
xslConfusedtylesheet, the root element, has the version as 2.0. This tells the processor the stylesheet is written in XSLT2.0.

The code has 1 template, which matches the root element of the input document, "/items". And when this template is applied to the root element it writes the root element of the output document("items").

Inside the "<items>" tag we have xsl:for-each-group. This instruction is used to group nodes(nodes which match the expression in @select) based on the values which the expressions in @group-by get evaluated to.
i.e., in this example, the for-each-group groups all "item"s based on their @type.
Or, to be simpler, in this example, all the "item" with @type = "A" fall in 1 group, with @type="B" in another and the rest("C") fall in other group.

The next tag is:
Code:
<item type="{current-grouping-key()}">.....</item>

the current-grouping-key() holds the value of the current-group's "group-by" value. i.e., the key value with which the current group has been distinguished. In this case, "A" for the first group, "B" for second, etc.

In the <item> do we have xsl:for-each which has "current-group()" as its select expression. current-group() gets you the access to all the nodes of the current group(that you are iterating on using for-each-group). i.e., all the "item" of the group. Hence, creating <item> with the value of the elements in the group.

Note: The grouping capabilities of XSLT2.0 aren't just limited to this example.
-Lingamurthy CS
Reply

Check for new replies

Forum Jump:


Users browsing this thread: 1 Guest(s)