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

How to group flat xml into 2 levels in xslt 2.0

I have an almost flat xml with several entries having info related to headings which are to be displayed before the entries' metadata. These headings can be in two levels and second level is optional. Kindly suggest a way to achieve that. Input…
Karma-yogi
  • 138
  • 11
-1
votes
2 answers

unable to add element in xml using xslt

I am new to xslt. I have a small xml code snippet as below. ABC@gmail.com And I have xslt code is below.
user3141034
  • 161
  • 3
  • 5
  • 15
-1
votes
1 answer

XSLT Removal of duplicate with multiple loops

I have to convert the below XML using the XSLT. Input XML is 1000909090
Victor
  • 333
  • 2
  • 5
  • 20
-1
votes
1 answer

Sum based on Element attribute in XSLT transformation

I am facing a problem in transformation of XML. I need to transform an output in text file as with ',' separated. I need to do the total based on type Descriptor. Output should look like: Co code ID type amount DEEP1 12345 phone 14 DEEP1 …
-1
votes
2 answers

Find out if all elements of a certain id have the same district

I am looking for a solution for the following problem. I want to know if all objects with a certain ID have the same district: Z001
Fareed
  • 3
  • 1
-1
votes
1 answer

Grouping multiple elements with same name

This is an extension to the question I asked earlier - XSLT 1.0 Grouping with multiple elements with same name The output format has changed and hence reposting. I have an XML that looks like -
-2
votes
1 answer

XML to pipe-delimited - How to copy/duplicate data to different rows

I'm new to XSLT and trying to transform from XML to pipe-delimited format. The problem that I'm having is that in the output, each claim has to be duplicated for each service line. Expected Output: EP030315706890704|TESTSUBMITTER|FAMILY…
-2
votes
2 answers

how to copy the parent node and all the child nodes of that parent with specific attribute should be present both in parent and child

i have this xml file....i have to check the status of SE/SSE ...if it is active then it will get inside the Details tag....it will read the status...if it is active then it will read the details tag , unless it ll discard that details node. Like…
mohan
  • 447
  • 4
  • 11
  • 26
-2
votes
1 answer

xslt grouping by calling template

I am new to xslt and trying to learn how to learn grouping using keys and using templates. Can somebody help me on how can do the following in xslt. I have to call a template from another template to do the transformation. Thanks here is my…
-3
votes
1 answer

Separate duplicates from unique

I tried with many XSLT methods like Key, for-each-group and match method options, but it is not working for me. Input XML: ABC
ABC
  • 1
  • 2
-3
votes
1 answer

XSLT Sequence Number Generation

I am preparing one flat file from XMl using XSLT 2.0. My input XML is A A1 A A2 B
Gnana
  • 2,130
  • 5
  • 26
  • 57
1 2 3
36
37