Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use group by in xslt

Tags:

group-by

xslt

I have a xml that has so many elements and most of that contain attributes.. for some of the attributes values are same so I need to group them and generate diff xml. I/p Ex:

<TestNode>
 <ABC1 value="10.7" format="$" />
 <ABC2 value="10.5" format="$" />
 <ABC3 value="20" format="Rs" />
 <ABC4 value="50" format="Rs" />
 <ABC5 value="10.5" format="$" />
</TestNode>

I need to group the rows by format. Note: Format is not fixed... it may grow ... O/P Ex: is it possible to get ? Thanks in advance...

like image 377
Amit Avatar asked Feb 25 '10 12:02

Amit


People also ask

What is group by in XSLT?

Relational databases have always offered a feature known as grouping, that is, sorting a collection of records on a field or combination of fields and then treating each subcollection that has the same value in that sort key as a unit.

What is current grouping key in XSLT?

The value used to select the items in the current group. The current-grouping-key() function is only useful inside an <xsl:for-each-group> element with a group-by or group-adjacent attribute. Calling current-grouping-key() anywhere else returns the empty sequence.

What is XSLT format?

XSLT (Extensible Stylesheet Language Transformations) is a language originally designed for transforming XML documents into other XML documents, or other formats such as HTML for web pages, plain text or XSL Formatting Objects, which may subsequently be converted to other formats, such as PDF, PostScript and PNG.


2 Answers

In XSLT 1.0 you would use Muenchian grouping.

Define a key "format", from which we can easily select all elements given a format name. Than apply Muenchian grouping to find the unique formats in the input.

Then it gets simple. The "*" template will be applied once per format, and uses the key() to fetch all entries for that format.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="xml" indent="yes" />

    <xsl:key name="format" match="TestNode/*" use="@format" />

    <xsl:template match="TestNode">
        <body>
            <xsl:apply-templates select="*[generate-id(.)=generate-id(key('format',@format)[1])]"/>
        </body>
    </xsl:template>

    <xsl:template match="*">
        <format format="{@format}">
          <xsl:copy-of select="key('format', @format)" />
        </format>
    </xsl:template>

</xsl:stylesheet>
like image 159
Lachlan Roche Avatar answered Sep 27 '22 21:09

Lachlan Roche


In XSLT 2.0 you should be able to do it with <xsl:for-each-group>, current-grouping-key() and current-group()

Example:

<xsl:for-each-group 
    select="TestNode/*"
    group-by="@format"
>
    <group format="{current-grouping-key()}">
        <xsl:for-each select="current-group()">
            <xsl:copy-of select="."/>
        </xsl:for-each>
    </group>
</xsl:for-each-group>

See: http://www.w3.org/TR/xslt20/#grouping

like image 35
Roland Bouman Avatar answered Sep 27 '22 20:09

Roland Bouman