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
vote
2 answers

Selecting Distinct Values using Custom Function under ForEach in XSLT

I need to ignore duplicate values while iterating in ForEach loop with Custom Function. I have below examples and share xslt which am trying to do. I can't apply foreach group in xslt 2.0, as it will break existing Code Functionality. Am expecting…
1
vote
0 answers

Club XML nodes together based on similar subtags. The clubbed node should also contain the non-similar subtags

I have just started learning xslt , please forgive me for for asking a straight solution. I want to club tags data into tag which have common , , . The remaining data , which…
1
vote
2 answers

grouping based on non-identical line items xsl1.0

I have requirement as below to implement transformation using only XSL1.0, First condition is Group line items based on parentLineNumber. Then the second condition is to ignore the invoice line when ParentLinenumber and LineNumber is same when only…
1
vote
1 answer
1
vote
1 answer

Grouping XSLT elements by value (XSLT 1.0)

I am having a really hard time trying to group different elements by a common value using XSLT 1.0. Using the following XML: ABCD123
1
vote
2 answers

Grouping dynamically

I'm trying to group the data together by summing a node adjacently. Example
Adrian
  • 59
  • 6
1
vote
1 answer

How to remove looping elements using XSLT Transformations where some tag have no values

ABC_PQRST0123456-001_1 4 1,2 ABC_PQRST0123456-001_2 1
Harsha
  • 11
  • 2
1
vote
1 answer

Remove Duplicate Node of second element using XSLT

I don't have much knowledge on xslt . I am trying to remove some duplicate node from my input xml but the nodes are not exactly duplicate . The PremiseId value is duplicate but the latitude, Longitude, XCoordinate and YCoordinate values are…
1
vote
1 answer

Can i create an child element counter in XSLT 1.0?

Giving the following source XML, i have processes a and b working (sources and results below) Now, how can i get to the expected exhibit c results below ? Extra points if it can be done in natural xslt 1.0 without resorting to a JAVA counter! Any…
Jim Cusler
  • 23
  • 3
1
vote
1 answer

How to find specific string within a group of like-named elements

For the XML below, how would I find which Election, with the latest date if there are multiple elections elected, each employee has chosen. A default value of 'Bronze' would be used if all elections say 'Waive' or when there are no elections for…
BryanG
  • 17
  • 2
1
vote
1 answer

Splitting Multiline XML tag into multiple Nodes

I have a XML below, where new lines are added after each line at Note__c tag. I need to produce the XML by splitting them into multiple Note__c tags. Input XML-
Sugata Bagchi
  • 123
  • 11
1
vote
1 answer

How to Create an Element from Two Surrounding Elements?

I am stuck with an XML to XML transformation using XSLT 2.0 where I need to transform this:

some mixed content START:attr="value" more mixed content END other mixed content

To this:

some mixed content

1
vote
1 answer

I'm using maps for streaming and grouping, need advice on how to improve the performance

My Source data is like this, and it's a really large xml of 2+ GB.
Adrian
  • 59
  • 6
1
vote
3 answers

XSLT 2.0: Issues creating HTML table with dynamic rows & columns

I'm creating an HTML table that is based on dynamic columns(Hostname) and rows(VLAN). I'm running into an issue after the first position data(1 row for all hosts) in the is written to the table; selects the 2nd position data just fine, but the…