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
3
votes
1 answer

List unique values of an attribute within a group only for specific criteria in XSL 1.0

I need to list the unique values of an attribute in a group, when another attribute has a specific value. Making this work in XSL 1.0 is very tricky to understand. Thanks to another post, I now have the groupings defined to allow me to perform…
MarkT
  • 81
  • 7
3
votes
2 answers

Saxon cannot find function: current-group

I am trying to use Saxon with XSLT stylesheets and using the code examples in the XSLT2 spec (http://www.w3.org/TR/xslt20/#xsl-for-each-group) …
peter.murray.rust
  • 37,407
  • 44
  • 153
  • 217
3
votes
1 answer

xslt 1.0 - how to have nested grouping with element of same level

I have an xml of the following form id1 SL0001 NEW id1 SL0001
3
votes
1 answer

Sort data in the xml alphabetical order

Input XML : Bill state Auto state
Blossom
  • 127
  • 2
  • 14
3
votes
2 answers

xslt grouping by every attribute

I have multiple types of xml messages I need to "compact" by grouping multiple nodes under the same parent (same parent meaning they share the same node name and every attribute declared is also equal). For example:
Ed Fox
  • 173
  • 1
  • 9
2
votes
1 answer

Using XSLT muenchian grouping to calculate sports team standings (wins/losses)?

I have been struggling for days to determine how to take an XML file of game results (teams and final scores) and generate a team standings list that shows each team along with how many times they won, lost or tied. The results should also be sorted…
Sam J.
  • 23
  • 2
2
votes
2 answers

Performing a “Group By” with sum function in XSLT 1.0

I want a result organized like following table: **Costc 1000** Product code Quantity Total amount SALESCOST 1 120.04 LEASINGRENT 1 59.90 **Costc 2000** Product code Quantity Total…
user1200589
  • 23
  • 1
  • 3
2
votes
3 answers

Groups two xml files like a sql group-by [2]

This is an evolution of my ask here : Groups two xml files like a sql group-by The Example given and Dimitre Solution was counting distinct isbn value. Now modify library xml to have mylibrary.xml :
Seb
  • 141
  • 2
  • 7
2
votes
1 answer

Marklogic XSLT 2.0 bug with grouping (starting-with)

I'm using xdmp:xslt-invoke() to transform documents in Marklogic. That works fine but today I faced a problem with using (while using group-adjacent works as expected in other parts of my…
2
votes
2 answers

XSLT : Problem with complex grouping

I'm struggling with getting 'for-each-group' working, I recently switched to xslt 2 but have still some job to do to get it all understood. I'm trying to clean out some files received from Framemaker MIF (flat xml), and while in most cases the data…
Wokoman
  • 1,089
  • 2
  • 13
  • 30
2
votes
2 answers

Removing duplicate XML nodes in XSLT

I would appreciated if someone could help me to create xslt to remove duplicates nodes from XML based on duplicated element's value(PlayBack--ControlInfo-ControlName). I want to remove all the duplicate…
2
votes
2 answers

Grouping method to maintain nested elements XSLT 2.0 - separating the excess

I'm grouping bulleted items and embedding them as a second list of bulleted items inside some list elements. I can get the items to group, but my recursion template is selecting everything from my current position in the doc to the end. I need to…
2
votes
1 answer

XSLT 1.0 Grouping on multiple values on multiple levels

edited in response to comments * Hello, I am an XSLT noob and need some help. I am trying to do an filter/group combination with XSLT 1.0 (can't use XSLT 2.0 for this application). Here is an example of the xml
Jeffrey Hersh
  • 73
  • 1
  • 8
2
votes
1 answer

XSLT split result in groups of 3 while ignoring input tree structure

I studied the solution for "XSLT split result in groups of 3" with interest. The elements in the cited example are all under one node. When I extended the example data to contain 2 branches of , like it is shown below,
Bumblevee
  • 69
  • 1
  • 5
2
votes
3 answers

How to separate similar data elements with a symbol(;) in XSLT

My source code is below. I am having similar data elements with different values. Below example I am having 3 phone numbers and I wants to have all in single line with a separator (;) I used concatenate function but no use
1
2
3
36 37
Position