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

Grouping is not working in XSLT 1.0

I have a XML like below. S-4LS16L 5550 1800 5550 1800 5550
0
votes
2 answers

XSLT current-groups() issue

I've been having a bit of trouble with an HTML file that I'm trying to translate. Basically, the relevant part of the source structure as it currently stands is this:

Dan McElroy
  • 426
  • 4
  • 19
0
votes
3 answers

XSLT 1.0 Grouping

I need to apply XSLT 1.0 transformation to following XML: 2013 13 13
jlp
  • 9,800
  • 16
  • 53
  • 74
0
votes
1 answer

XSLT Function sum() Not Calculating Nodes

Thank you all for taking the time to view my problem. I am having trouble summing the node when the nodes value is different, but works if it is the same. Here is my XML - 75.00
proximityFlying
  • 153
  • 3
  • 13
0
votes
1 answer

XSLT can't figure out how to group properly

I have the following XML file, which is exported from an Oracle-DB: http://pastebin.com/0yPcc7HT I need to transform it to the following structure: 59957
gasparuff
  • 2,295
  • 29
  • 48
0
votes
1 answer

XSLT grouping items by count

I have the following list of items. Item1 Item2 Item3 Item4 Item5
John Fu
  • 1,812
  • 2
  • 15
  • 20
0
votes
1 answer

How to extend a Muenchian XML grouping?

I have this XML: Thanks to hr_117's help, I managed to do…
Tintin81
  • 9,821
  • 20
  • 85
  • 178
0
votes
2 answers

XSLT group-by throws an error

The xml is as below: Apple Fruit Honda Car
MPP
  • 65
  • 1
  • 7
0
votes
1 answer

XSLT: merging files but with better performance of the process

I have two XML files and desire a merger, the criterion for this merger is as follows: nodes1.xml file content: a joe b sam
0
votes
2 answers

Sort groups by arregate element property in xslt

I'm transforming some xml using xslt (version 1.0, using MSXSL). Say my xml data looks like this:
Aa10Ab35
Michel de Ruiter
  • 7,131
  • 5
  • 49
  • 74
0
votes
1 answer

Get distinct values from xml

My sample xml looks below: I need to get the distinct states from xml. I am using xslt 1.0 in vs 2010 editor. 2 DE
Blossom
  • 127
  • 2
  • 14
0
votes
1 answer

XML - Combine different tags using XSLT 2

I have already asked something similar here regarding the same file (XML - combine tags to children with XSLT). Unfortunately my XML has grown so I need your help again please.
gasparuff
  • 2,295
  • 29
  • 48
0
votes
1 answer

XSLT sort xml based on values that have to be calculated dynamicly

I have to sort an xml file based on several values. The input xml has the following structure: 100 2000 30003
Christian Fries
  • 444
  • 3
  • 12
0
votes
1 answer

xslt multiple grouping Format data in a table some columns are blank

With XSLT 1.0, how can I change the following: