2

Which is the best way to group Elements based on attribute value using XSLT? Would it be better to use XSLT 2.0 or higher?

Many thank in advance for your help

Thomas


Original XML:

<transaction>    
  <record type="1" >
    <field number="1" >
        <item >223</item>
    </field>
  </record>

  <record type="14" >
    <field number="1" >
        <item >777</item>
    </field>
  </record>

  <record type="14" >
    <field number="1" >
        <item >555</item>
    </field>
  </record>      
</transaction>

Result after grouping:

<transaction>
  <records type="1" >
      <record type="1" >
        <field number="1" >
            <item >223</item>
        </field>
      </record>
  </records>

  <records type="14" >
      <record type="14" >
        <field number="1" >
            <item >777</item>
        </field>
      </record>

      <record type="14" >
        <field number="1" >
            <item >555</item>
        </field>
      </record>
  </records>
</transaction>
2
  • 1
    The answer is "yes". If you are able to use XSLT 2.0, then it would almost certainly be better to use it. In this case, you can make use of the xsl:for-each-group construct, which makes grouping much easier. So, in this case you would do <xsl:for-each-group select="record" group-by="@type" /> Commented Oct 11, 2017 at 17:05
  • Hi Tim! Many thanks for your fast reply. I tried it with the following template: <xsl:template match="transaction/record"> <xsl:for-each-group select="record" group-by="@type"> <xsl:apply-templates/> </xsl:for-each-group> </xsl:template> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> </xsl:stylesheet> The result XML contains just the root element. Many thanks again for your help. Thomas <transaction> </transaction> Commented Oct 12, 2017 at 8:03

1 Answer 1

1

In XSLT 2.0, you can use xsl:for-each-group, but if you are going to do <xsl:for-each-group select="record" group-by="@type"> then you must be positioned on the transaction record at that point.

Additionally, you will need to make use of current-group to get all the record elements within the group.

Try this XSLT

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

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

<xsl:template match="transaction"> 
    <xsl:copy>
        <xsl:for-each-group select="record" group-by="@type"> 
            <records type="{current-grouping-key()}" >
                <xsl:apply-templates select="current-group()" />
            </records>
        </xsl:for-each-group>
    </xsl:copy>
</xsl:template> 

<xsl:template match="@*|node()"> 
    <xsl:copy> 
        <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
</xsl:template> 
</xsl:stylesheet> 
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.