Search code examples
xsltgroupingexcept

current-group() except for one element in xslt


The below is my input xml. I'm trying group by using current-group() function but it is not meeting my requirement, below I have provided the details.

        <UsrTimeCardEntry>
            <Code>1<Code>
            <Name>TC1</Name>
            <Person>
                <Code>074</Code>
            </Person>
        </UsrTimeCardEntry>
        <UsrTimeCardEntry>
            <Code>2<Code>
            <Name>TC2</Name>
            <Person>
                <Code>074</Code>
            </Person>
        </UsrTimeCardEntry>

I want to group it by Person/Code so that it looks like this

   <Person Code="074">
       <UsrTimeCardEntry>
              <Code>1</Code>
              <Name>TC1</Name>
       </UsrTimeCardEntry>
       <UsrTimeCardEntry>
              <Code>2</Code>
              <Name>TC2</Name>
       </UsrTimeCardEntry>
</Person>

For which I'm using the below xslt, but it is again copying the Person which I don't want, what it that I'm missing here, I tried using current-group() except and not[child::Person] but that too did not work.

<xsl:template match="businessobjects">
    <xsl:for-each-group select="UsrTimeCardEntry" group-by="Person/Code">
        <Person Code="{current-grouping-key()}">
            <xsl:copy-of select="current-group()"></xsl:copy-of>
        </Person>
    </xsl:for-each-group>
</xsl:template>

Solution

  • Instead of using xsl:copy-of here, use xsl:apply-templates, then you can add a template to ignore the Person node

    <xsl:template match="Person" />
    

    This assumes you are also using the identity template to copy all other nodes normally.

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    

    Try this XSLT

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
        <xsl:output method="xml" indent="yes" />
    
        <xsl:strip-space elements="*" />
    
        <xsl:template match="businessobjects">
            <xsl:for-each-group select="UsrTimeCardEntry" group-by="Person/Code">
                <Person Code="{current-grouping-key()}">
                    <xsl:apply-templates select="current-group()" />
                </Person>
            </xsl:for-each-group>
        </xsl:template>
    
        <xsl:template match="Person" />
    
        <xsl:template match="@*|node()">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
            </xsl:copy>
        </xsl:template>
    </xsl:stylesheet>