'How to improve/refactor this xslt?

Given the following xml :

<tree>
    <val>0</val>
    <tree>
        <val>1</val>
        <tree>
            <val>3</val>
        </tree>
        <tree>
            <val>4</val>
        </tree>
    </tree>
    <tree>
        <val>2</val>
        <tree>
            <val>5</val>
        </tree>
        <tree>
            <val>6</val>
        </tree>
    </tree>
</tree>

I need to transform it into this xml:

<root>0
    <frst>1
        <leaf>3</leaf>
        <leaf>4</leaf>
    </frst>
    <second>2
        <leaf>5</leaf>
        <leaf>6</leaf>
    </second>
</root>

This is my attempt that gives the same result, I recently started learning XSLT i'm not sure what other option I have, can this be improved or done in another way ? Thank you for your help

This is my attempt :

<?xml version='1.0' encoding='utf-8'?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" encoding="UTF-8"/>
    <xsl:template match="/tree">
        <root>
            <xsl:apply-templates />
        </root>
    </xsl:template>

    <xsl:template match="val">
        <xsl:value-of select="."/>
    </xsl:template>

    <xsl:template match="tree">
        <xsl:choose>
            <!--  IF HAS CHILDREN -->
            <xsl:when test="child::tree">
                <xsl:if test="(count(preceding-sibling::tree)+1) = 1">
                    <frst>
                        <xsl:apply-templates/>
                    </frst>
                </xsl:if>
                <xsl:if test="(count(preceding-sibling::tree)+1) = 2">
                    <second>
                        <xsl:apply-templates/>
                    </second>
                </xsl:if>
            </xsl:when>
            <!--  ELSE IS A LEAF  -->
            <xsl:otherwise>
                <leaf>
                    <xsl:apply-templates/>
                </leaf>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>

test test



Solution 1:[1]

I would think the conditions can be written in match patterns:

  <xsl:template match="tree[tree][1]">
    <frst>
      <xsl:apply-templates/>
    </frst>
  </xsl:template>
  
  <xsl:template match="tree[tree][2]">
    <second>
      <xsl:apply-templates/>
    </second>
  </xsl:template>
  
  <xsl:template match="tree[not(tree)]">
    <leaf>
      <xsl:apply-templates/>
    </leaf>
  </xsl:template>

although I guess your current code doesn't process the third/fourth/fifth.. tree children so an additional <xsl:template match="tree[tree][position() > 2]"/> might be necessary.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1