Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XSLT - Recursive Template Usage to get nested XML nodes

I'm facing a problem working with XML and XSLT. I want to create a XML file that looks like this:

<Root>
    <TopNode>
        <ChildNode>
            <!-- Some elements -->
            <ListOfChilds>
                <ChildNode/> <!-- 0 to N ChildNodes within a Childnode which can again have ChildNodes as well and so on -->
            </ListOfChilds>
            <!-- Some more elements -->
        </ChildNode>
        <ChildNode>
            ...
        </ChildNode>
    </TopNode>
<Root>

As you can see, some kind of recursion is needed as every ChildNode can contain several ChildNodes that can contain several ChildNodes... and so on. I tried to achieve this by using Templates for the <Root>, <TopNode>and <ChildNode>elements. My XSLT looks like this:

<xsl:template match="/">
    <Root>
        <xsl:apply-templates select="TopNode"/>
    </Root>
</xsl:template>

<xsl:template match="TopNode">
    <TopNode>
        <xsl:apply-templates select="ChildNode"/>
    </TopNode>
</xsl:template>

<xsl:template match="ChildNode">
    <ChildNode>
        <!-- Some elements -->
        <ListOfChilds>
            <xsl:if test="ChildNode">
                <xsl:apply-templates select="ChildNode"/>
            </xsl:if>
        </ListOfChilds>
        <!-- Some more elements -->
    </ChildNode>
</xsl:template>

However, the only output I get in my XML file is <Root/>. Could you guys please tell me what's going wrong in my transformation? Is the way I want to do this theoretically working at all or should I try a completely different approach? I'm really kinda lost right now and any help would be much appreciated! Thank you!

like image 970
DerSöllinger Avatar asked Jul 11 '26 06:07

DerSöllinger


1 Answers

Recursion is done by XSLT automatically if you use xsl:apply-templates, which is applied to the children. If you have matching templates for these children (and you do) and apply templates inside them, you have recursion. You are on the right track.

<xsl:if test="ChildNode">
    <xsl:apply-templates select="ChildNode"/>
</xsl:if>

This is not necessary. Apply-templates only has effect if there are ChildNode elements, so the xsl:if is redundant.

In essence you are using the right approach, but you made a small mistake in the beginning:

<xsl:apply-templates select="TopNode"/>

The context node here is /, the root node. But your element is not TopNode, but Root. Change it to Root/TopNode and you will see output.

like image 137
Abel Avatar answered Jul 13 '26 09:07

Abel



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!