Sunday, December 31, 2023

XSLT 3.0 grouping use case

I've just been playing this evening, trying to improve XalanJ prototype processor's XSLT 3.0 xsl:for-each-group instruction's implementation. Following is an xsl:for-each-group instruction use case, that I've been trying to solve.

XML input document,

<?xml version="1.0" encoding="utf-8"?>

<root>

  <a>

    <itm1>hi</itm1>

    <itm2>hello</itm2>

    <itm3>there</itm3>

  </a>

  <b>

    <itm1>this</itm1>

    <itm2>is</itm2>

    <itm3>nice</itm3>

  </b>

  <c>

    <itm1>hello</itm1>

    <itm2>friends</itm2>

  </c>

  <d>

    <itm1>this is ok</itm1>

  </d>

</root>

XSLT 3.0 stylesheet, using xsl:for-each-group instruction to group XML instance elements from an XML document cited above,

<?xml version="1.0" encoding="utf-8"?>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"

                         version="3.0">

      <xsl:output method="xml" indent="yes"/>

     <xsl:template match="/root">

           <result>

               <xsl:for-each-group select="*" group-by="(count(*) eq 1) or (count(*) eq 3)">

            <group groupingCriteria="{if (current-grouping-key() eq true()) then '1,3' else 'not(1,3)'}">

                <xsl:copy-of select="current-group()"/>

            </group>

              </xsl:for-each-group>

          </result>

      </xsl:template>

</xsl:stylesheet>

The stylesheet transformation result, of above cited XSLT transform is following as produced by XalanJ,

<?xml version="1.0" encoding="UTF-8"?><result>

  <group groupingCriteria="1,3">

    <a>

    <itm1>hi</itm1>

    <itm2>hello</itm2>

    <itm3>there</itm3>

  </a>

    <b>

    <itm1>this</itm1>

    <itm2>is</itm2>

    <itm3>nice</itm3>

  </b>

    <d>

    <itm1>this is ok</itm1>

  </d>

  </group>

  <group groupingCriteria="not(1,3)">

    <c>

    <itm1>hello</itm1>

    <itm2>friends</itm2>

  </c>

  </group>

</result>

Achieving such XML data grouping, was very hard with XSLT 1.0 language. Thank god, we've XSLT 3.0 language available now.


Thursday, December 28, 2023

Managing complexity of XPath 3.1 'if' expressions, in the context of XSLT 3.0

I've just been playing around, with the following XSLT transformation example, and thought of sharing this as a blog post here.

Let's consider following XSLT 3.0 stylesheet, that we'll use to transform an XML document mentioned thereafter,

<?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"

                         xmlns:fn0="http://fn0"

                         exclude-result-prefixes="xs fn0"

                         version="3.0">

  <xsl:output method="xml" indent="yes"/>

  <xsl:variable name="date1" select="xs:date('2005-10-12')" as="xs:date"/>

  <xsl:template match="/root">

      <root>

          <xsl:copy-of select="if (fn0:func1($date1)) then a else b"/>

     </root>

  </xsl:template>

  <!-- An XSLT stylesheet function, that performs a specific boolean valued computation. The result of this function, is used to perform computations of distinct branches of XPath 'if' condition used within xsl:copy-of instruction written earlier above. -->

 <xsl:function name="fn0:func1" as="xs:boolean">

     <xsl:param name="date1" as="xs:date"/>

     <xsl:sequence select="if (current-date() lt $date1) 

                                                                               then true() 

                                                                               else false()"/>

   </xsl:function>

</xsl:stylesheet>

The corresponding XML instance document is following,

<?xml version="1.0" encoding="utf-8"?>

<root>

    <a/>

    <b/>

</root>

The two possible XSLT transformation results (depending upon the result of following XPath expression comparison : current-date() lt $date1, for the above mentioned XSLT transformation are following:

<?xml version="1.0" encoding="UTF-8"?><root>

  <b/>

</root>

and,

<?xml version="1.0" encoding="UTF-8"?><root>

  <a/>

</root>

Within the above mentioned XSLT transformation example, we may observe how, the XPath 3.1 'if' expressions have been written to achieve the desired XSLT transformation results. We're able to write stylesheet functions that may be significantly complex to produce boolean result, which may act as XPath 'if' expression branching condition.

I hope that, the above mentioned XSLT transformation example is useful.


Wednesday, December 27, 2023

XML data grouping with XSLT 3.0, illustrations

I've just been playing this morning, writing an XSLT 3.0 stylesheet, that does grouping of an XML input data as follows (that I wish to share with XML and XSLT community).

XML input document,

<root>

  <a>

    <m/>

  </a>

  <b>

    <n/>

  </b>

  <a>

    <o/>

  </a>

  <a>

    <p/>

  </a>

  <a>

    <q/>

  </a>

  <b>

    <r/>

  </b>

  <b>

    <s/>

  </b>

</root>


XSLT 3.0 stylesheet, that does grouping of XML document's data mentioned above (i.e, grouping of xml element children of element "root"),

<?xml version="1.0" encoding="utf-8"?>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"                

                         version="3.0">

  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="/root">

     <xsl:for-each-group select="*" group-by="name()">

        <xsl:element name="{current-grouping-key()}">

           <xsl:copy-of select="current-group()/*"/>

        </xsl:element>

     </xsl:for-each-group>

  </xsl:template>

</xsl:stylesheet>


The XSLT transformation output, of this XML document transform is following,

<?xml version="1.0" encoding="UTF-8"?><a>

  <m/>

  <o/>

  <p/>

  <q/>

</a><b>

  <n/>

  <r/>

  <s/>

</b>


The XML data grouping algorithm implemented by the XSLT stylesheet illustrated above is following,

The XML element children of element "root", are formed into multiple groups (there are two XML data groups that're possible for this stylesheet transformation example.) on the basis of XML element names (the XML sibling elements which are child elements of element "root").

I hope that, this XSLT stylesheet example has been useful for us to study.

This XSLT stylesheet example, has been tested with Apache XalanJ's XSLT 3.0 prototype processor.