Search code examples
xmlxsltxslt-2.0xslt-grouping

XSLT 2.0 - Grouping and Sorting -<xsl:for-each-group>


I want to group together footnote by fnrtoken in order of fnlabel. all the with fnrtoken should be grouped together order by label . but if any footnote without fnlabel is between those footnote then new group should be created for that footnote and again start new group for remaiing footnote with fnlable

Input:

<endnotes>
    <footnote fntoken="aasdf" fnrtoken="78hyyj">
        <fnlabel>2</fnlabel>
        <para></para>
    </footnote>
    <footnote fntoken="aasdf" fnrtoken="78jjjj">
        <fnlabel>1</fnlabel>
        <para></para>
    </footnote>
    <footnote fntoken="aasdf" fnrtoken="7900hj">
        <fnlabel>4</fnlabel>
        <para></para>
    </footnote>
    <footnote fntoken="aasdf">
        <fnlabel>3</fnlabel>
        <para></para>
    </footnote>
    <footnote fntoken="aasdf">
        <fnlabel>5</fnlabel>
        <para></para>
    </footnote>
</endnotes>


Output:
<footenotegrp>
    <footnote fntoken="aasdf" fnrtoken="78jjjj">
        <fnlabel>1</fnlabel>
        <para></para>
    </footnote>
    <footnote fntoken="aasdf" fnrtoken="78hyyj">
        <fnlabel>2</fnlabel>
        <para></para>
    </footnote>
</footenotegrp>
<footenotegrp>
    <footnote fntoken="aasdf">
        <fnlabel>3</fnlabel>
        <para></para>
    </footnote>
</footenotegrp>
<footenotegrp>
    <footnote fntoken="aasdf" fnrtoken="7900hj">
        <fnlabel>4</fnlabel>
        <para></para>
    </footnote>
</footenotegrp>
<footenotegrp>
    <footnote fntoken="aasdf">
        <fnlabel>5</fnlabel>
        <para></para>
    </footnote>
</footenotegrp>

Solution

  • It seems to me you first want to sort and then you want to group using group-adjacent="exists(@fnrtoken)":

    <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 indent="yes"/>
    
        <xsl:template match="/*">
            <root>
                <xsl:variable name="sorted" as="element(footnote)*">
                    <xsl:perform-sort select="footnote">
                        <xsl:sort select="fnlabel"></xsl:sort>
                    </xsl:perform-sort>
                </xsl:variable>
                <xsl:for-each-group select="$sorted" group-adjacent="exists(@fnrtoken)">
                    <xsl:choose>
                        <xsl:when test="current-grouping-key()">
                            <footnotegrp>
                                <xsl:copy-of select="current-group()"/>
                            </footnotegrp>
                        </xsl:when>
                        <xsl:otherwise>
                            <xsl:for-each select="current-group()">
                                <footnotegrp>
                                    <xsl:copy-of select="."/>
                                </footnotegrp>
                            </xsl:for-each>
                        </xsl:otherwise>
                    </xsl:choose>
                </xsl:for-each-group>
            </root>
        </xsl:template>
    
    </xsl:stylesheet>
    

    That transforms

    <?xml version="1.0" encoding="UTF-8"?>
    <endnotes>
        <footnote fntoken="aasdf" fnrtoken="78hyyj">
            <fnlabel>2</fnlabel>
            <para></para>
        </footnote>
        <footnote fntoken="aasdf" fnrtoken="78jjjj">
            <fnlabel>1</fnlabel>
            <para></para>
        </footnote>
        <footnote fntoken="aasdf" fnrtoken="7900hj">
            <fnlabel>4</fnlabel>
            <para></para>
        </footnote>
        <footnote fntoken="aasdf">
            <fnlabel>3</fnlabel>
            <para></para>
        </footnote>
        <footnote fntoken="aasdf">
            <fnlabel>5</fnlabel>
            <para></para>
        </footnote>
    </endnotes>
    

    into

    <?xml version="1.0" encoding="UTF-8"?>
    <root>
       <footnotegrp>
          <footnote fntoken="aasdf" fnrtoken="78jjjj">
                   <fnlabel>1</fnlabel>
                   <para/>
             </footnote>
          <footnote fntoken="aasdf" fnrtoken="78hyyj">
                   <fnlabel>2</fnlabel>
                   <para/>
             </footnote>
       </footnotegrp>
       <footnotegrp>
          <footnote fntoken="aasdf">
                   <fnlabel>3</fnlabel>
                   <para/>
             </footnote>
       </footnotegrp>
       <footnotegrp>
          <footnote fntoken="aasdf" fnrtoken="7900hj">
                   <fnlabel>4</fnlabel>
                   <para/>
             </footnote>
       </footnotegrp>
       <footnotegrp>
          <footnote fntoken="aasdf">
                   <fnlabel>5</fnlabel>
                   <para/>
             </footnote>
       </footnotegrp>
    </root>