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

XSL substring given two match variables

I'm trying to return a substring'ed value based on two matching strings 'Group -' and 'Experts Choice - ' Everything works accordingly to my requirements but the issue is that, it should return everything after 'Group -' and 'Experts Choice - '.…
Arty
  • 819
  • 3
  • 13
  • 24
0
votes
1 answer
0
votes
1 answer
0
votes
1 answer

XSLT: Group XML elements by type and output as HTML tables

I have XML containing elements describing the name,value,sfid,feildsection of objects. Objects are grouped by type feildsection as providersection and devidetype . my xml given blow Financial Change…
0
votes
1 answer

XSLT sorting - how to sort AND copy the whole input as sorted output

I am trying to sort an XML file using XSLT transformation, but it doesn't do what I want. I want to sort the XML lexicographically by the loc element. This is my original XML:
Alma Alma
  • 1,641
  • 2
  • 16
  • 19
0
votes
1 answer

Camel case conversion for special case also in XSLT

Below XSLT converts First character of each word to upper case.But Fails for special case (example:for input-> the 'lion ,king output is-> The 'Lion ,King). Need solution for the special case also.
0
votes
2 answers

XSLT group on multiple keys

This is the input file.
mario
  • 1
  • 2
0
votes
2 answers

How to Ignore specifc element value using value-of

Below my input Colorado DivIsIoN five and a half abc Here is my xslt my implemntation (xslt verions-1.0)
0
votes
1 answer

Need to show the same value once using XSLT

Prod 1 123 Prod 2 123
0
votes
1 answer

How to query all descendant nodes using single xpath expression with multiple conditions

The image shows the nodes in the xml file. I need to find the no of failed testgroups. If any one testcase fails the corresponding testgroup is assumed failed. In the image, failed testgroup count = 2. The main issue i face here is that in XSLT i…
Martin
  • 3,396
  • 5
  • 41
  • 67
0
votes
2 answers

Rails 4 : how to use UNIX_TIMESTAMP with group YEAR

I have the following code Call.group('YEAR(created_at)').count Which returns {2013=>81577, 2012=>93323, 2011=>79915, 2010=>59084, 2009=>55561} How can I use UNIX_TIMESTAMP for the years so that the UNIX_TIMESTAMP value is returned (ex.…
Alex B.
  • 9
  • 3
0
votes
1 answer

XSLT 2.0 - For-Each-Group in combination with Tokenize

I have a blob of text with delimiters that I'd like to format into an HTML table using XSLT 2.0 (saxon). The text blob (param myTable in this example) contains records separated with |c|. After the 6th record it should become a new row. There's…
N Simpson
  • 47
  • 7
0
votes
1 answer

Specific order for XSL Template output

I've got the following xml file:
9/18/2013 - Weight - 125 lbs 9/18/2013 - Blood Pressure - 120/80 mm Hg
jjasper0729
  • 285
  • 3
  • 18
0
votes
0 answers

selecting nodes based on the attribute value

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 shows each team along with how many times they won, lost or tied based on game status(played). I was…
0
votes
1 answer

sort the node data alphabetical order using xslt1.0

I would like to disply state and country names in alphabetical order. If there are any county1 node assosiated with state I need to display all states with in the counry name.however if there is no state that starts with a certain…
Blossom
  • 127
  • 2
  • 14