Skip to content

Instantly share code, notes, and snippets.

@jamescummings
Created February 23, 2017 15:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jamescummings/66bb7ce82266f9067e630d57aa973960 to your computer and use it in GitHub Desktop.
Save jamescummings/66bb7ce82266f9067e630d57aa973960 to your computer and use it in GitHub Desktop.
An XSLT to group and subGroup <l> elements
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs" version="2.0">
<xsl:output method="xml" indent="yes"/>
<!--
Group input like:
<root>
<l xml:id="ms1-26">
<q target="#ms1-q-4">4</q>
</l>
<l xml:id="ms1-27">
<q target="#ms1-q-4">4</q>
</l>
<l xml:id="ms1-28">
<q target="#ms1-q-4">4</q>
<q target="#ms1-q-4.1" type="sub">1</q>
</l>
<l xml:id="ms1-29">
<q target="#ms1-q-4">4</q>
<q target="#ms1-q-4.1" type="sub">1</q>
</l>
<l xml:id="ms1-30">
<q target="#ms1-q-4">4</q>
</l>
</root>
with subGrouping for <l> which have multiple <q> elements in them
-James Cummings 2017-02-22
-->
<!-- Match root element -->
<xsl:template match="/root">
<!-- copy this root element to the output -->
<xsl:copy>
<!-- select all the l elements inside it and group them by the thing they have
in common, in this case the 8th number of the id that their children q point to.
-->
<xsl:for-each-group select="l" group-by="q/@target/substring(., 8, 1)">
<!-- wrap a group element around each group -->
<group>
<!-- for each item in the current group, create groups adjacent to the truth or
falsehood of the count of q child elements being greater than one -->
<xsl:for-each-group select="current-group()" group-adjacent="boolean(count(q) gt 1)">
<!-- test whether the current-grouping-key() is true() (here using a shortcut
but could have tested it =true() or =false() explicitly if we'd wanted -->
<xsl:choose>
<xsl:when test="current-grouping-key()">
<!-- In the case the current grouping key is true, that is there is more than one q
then wrap it in a subGroup element
-->
<subGroup>
<!-- for each item in this current group (of l elements where there are more
than one q) copy it to the output. -->
<xsl:for-each select="current-group()">
<xsl:copy-of select="."/>
</xsl:for-each>
</subGroup>
</xsl:when>
<!-- otherwise, there is not more than one q element -->
<xsl:otherwise>
<!-- so for each of these just copy it to the output not being inside a subGroup -->
<xsl:for-each select="current-group()">
<xsl:copy-of select="."/>
</xsl:for-each>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</group>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment