Questions tagged [xslt-grouping]

Grouping mechanisms that are specific to XSLT. Should always be complemented with either the xslt-1.0, xslt-2.0 or xslt-3.0 tag to indicate the version used.

Grouping in XSLT 3

Grouping in XSLT 3, the current and latest version of XSLT since 2017, can be achieved primarily using the xsl:for-each-group instruction where you select the items to be grouped, the grouping population, with the select attribute and then have three different ways to group the population:

  1. the group-by attribute selecting a sequence of grouping keys by which the grouping population is to be grouped
  2. the group-adjacent attribute selecting a sequence of grouping keys by which adjacent items in the population are to be grouped
  3. the group-starting-with or group-ending-with attributes defining patterns to identify and start groups based on pattern matching of the initial (group-starting-with) or final (group-ending-with) member of a group

Access to the items of a currently processed group is given by the current-group() function, access to the current grouping key by the current-grouping-key() function.

The XSLT 3 specification gives at least one example for each grouping approach directly in the specification section https://www.w3.org/TR/xslt-30/#grouping-examples; below you find links to XSLT fiddles based on these examples:

Of course the different approaches can, for more complex tasks, be combined by nesting xsl:for-each-group instructions.

XSLT 3 with XPath 3.1 support can also group JSON represented as XPath 3.1 maps and arrays, here is a list of showing the previous XML grouping samples now using JSON input and directly grouping the map/array data structure returned by the parse-json function:

Positional grouping

Positional grouping can be used to split a sequence of items into groups of a certain size; in XSLT 2 or 3 this is easily achieved using e.g. for-each-group select="foo" group-adjacent="(position() - 1) idiv $chunk-size": https://xsltfiddle.liberty-development.net/asoTK9

https://martin-honnen.github.io/xslt/generic-positional-grouping-functions.xsl is a compact XSLT 3 module using higher-order functions importable by other code that needs to split up a sequence of items using positional grouping, you could use it as follows (Saxon-JS 2, Saxon 10 or higher all editions, Saxon 9.8 or higher PE and EE, Altova XML 2017 R3 or later)

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="3.0"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:mf="http://example.com/mf"
    xmlns:ex="http://example.com/ex"
    exclude-result-prefixes="#all"
    expand-text="yes">

  <xsl:import href="https://martin-honnen.github.io/xslt/generic-positional-grouping-functions.xsl"/>

  <xsl:function name="ex:wrap-rows" as="element()">
    <xsl:param name="group" as="item()*"/>
    <xsl:param name="pos" as="xs:integer"/>
    <xsl:param name="wrapper-name" as="xs:QName"/>
    <xsl:element name="{$wrapper-name}" namespace="{namespace-uri-from-QName($wrapper-name)}">
      <xsl:attribute name="index" select="$pos"/>
      <xsl:sequence select="$group"/>
    </xsl:element>
  </xsl:function>

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

  <xsl:template match="root">
    <root>
      <xsl:sequence select="mf:group-chunks(item, 3, ex:wrap-rows(?, ?, QName('', 'chunk')))"/>
    </root>
  </xsl:template>

  <xsl:template match="/">
    <xsl:next-match/>
    <xsl:comment>Run with {system-property('xsl:product-name')} {system-property('xsl:product-version')} {system-property('Q{http://saxon.sf.net/}platform')}</xsl:comment>
  </xsl:template>

</xsl:stylesheet>

to e.g. wrap any chunk into a container element.

Grouping in XSLT 2

Grouping in XSLT 2 also works with the xsl:for-each-group instruction as in XSLT 3, the main restrictions are that XSLT 2 does not support composite grouping keys (so to group on various items you need to concat or string-join them as single value (e.g. composite="yes" group-by="foo, bar" in XSLT 3 needs to be done as group-by="string-join((foo, bar), '|')")) and that pattern matching can only be done on nodes, not on primitive values.

The XSLT 2 specification gives at least one example for each grouping approach directly in the specification section https://www.w3.org/TR/xslt20/#grouping-examples; below you find links to XSLT fiddles based on these examples:

Grouping in XSLT 1.0

The preferred solution in XSLT 1.0 is to use the Muenchian grouping method:
http://www.jenitennison.com/xslt/grouping/muenchian.html

552 questions
2
votes
3 answers

Grouping elements and deleting duplicate nodes - XSLT 1.0

I have looked at Muenchian Grouping - group within a node, not within the entire document but it is not quite working for me. The Muenchian method alone does not do it either for me. I have also looked at XSLT 1.0: grouping and removing duplicate…
Peter
  • 1,786
  • 4
  • 21
  • 40
2
votes
1 answer

Grouping Child nodes under each Parent nodes in XSLT

I am new to the XSLT grouping concept. I am trying to group the below XML using XSLT 2.0 . 20 A
2
votes
1 answer

XSL transform xml rows with attributes to unordered list treeview

I have the following XML coming from a SharePoint control. I would like to transform using XSLT to produce a nested ul>li list. But I am having problem as I iterate each row, the primary folder repeats for each row, rather than making one primary…
Athapali
  • 1,091
  • 4
  • 25
  • 48
2
votes
1 answer

Counting distinct items in XSLT

I have XML like this:
Paul Reiners
  • 8,576
  • 33
  • 117
  • 202
2
votes
1 answer

xslt grouping and removing duplicates

A 20141112 2 1 12 .1 item a…
mnvbrtn
  • 558
  • 1
  • 8
  • 27
2
votes
2 answers

Move child Nodes to attributes conditionally

I am trying to transform this document but am fairly new to xslt and having tons of fun trying to get it right. The core node(truncated for simplicity) looks like this 221 Oscar…
2
votes
2 answers

XSLT 1.0 grouping multiple same nodes on same level with different values

I have a list of elements: CAR vehicile1 vehicile2 vehicile3
Klepstryk
  • 57
  • 1
  • 5
2
votes
3 answers

Nested grouping based on parent field using XSLT

This is a sample of the raw XML I'm working with:
Katie
  • 357
  • 1
  • 12
2
votes
1 answer

Group by and count in XSLT 2.0

I'm trying to make a table with counts grouped by labels. I would like to count how many times each levels of "standings_level" are in my file. Here is an excerpt of my XML file :
Julien Navarre
  • 7,653
  • 3
  • 42
  • 69
2
votes
2 answers

Replace unnessary characters in xml and sum them

I'm new to XSLT, I need to add all the price values. But the price values in XML have '-' and also no values and while doing sum I'm getting NaN. So i tried the below XSL, but still I'm unable to achieve my result. Below is a sample XML
Sai Kiran
  • 64
  • 8
2
votes
1 answer

Grouping and counting in XSLT 1.0

I have input XML: Paket Parti Paket Styche Styche And I want my output to display such as - Paket 2 Parti 1 Styche 2 Its is…
Kundan
  • 153
  • 1
  • 5
  • 15
2
votes
4 answers

XSLT, sort and group by year-date

Regarding Umbraco XSLT version 1. I have aprox. 150 news items in XML. Lets say like this (all is pseudocode until I get more familiar with this xml/xslt): 2008-10-20
Tillebeck
  • 3,493
  • 7
  • 42
  • 63
2
votes
1 answer

How to organize(group) nodes under a closed element - XSLT

I have tried simple grouping XML with XSLT 1.0 and it worked, but here I have something more complicated and actually different situation. So the XML structure is basically this:
--> some elements and stuff - not relevant
Syspect
  • 921
  • 7
  • 22
  • 50
2
votes
4 answers
2
votes
1 answer

XSL 1.0 Double Grouping

This is my first question here. I want to transform this xml using XSL 1.0 : 1 A Alice 1 A
Proqb
  • 335
  • 1
  • 3
  • 7
1 2
3
36 37