XSLT: recursion (with key?) vs nesting call-template

S

shaun roe

I have a document about 4 levels deep and in my XSLT I want to generate
a unique string ID for each basic element based on its path through the
hierarchy.

If I use recursion, I am continually accessing the root element ID, here
is a typical call:

<xsl:variable name="fullPath"
select="concat('p',../../../@id,'_c',../../@id,'_r',../@id,'_s',$slaveID)
"/>

I *could* do this by nesting call-templates and passing the current id
as a parameter. Is this likely to be more or less efficient?

e.g. starting xml:

<castle id="0>
<level id="2">
<room id="2"/>
<room id="3"/>
<room id="4"/>
</level>
<level id="3">
<room id="2"/>
<room id="3"/>
<room id="4"/>
</level>
</castle>


so heres an xslt:

<xsl:template match="castle">
<xsl:fullPath select="concat('c',@id)"/>
<thisCastle uid="{$fullPath}"/>
<xsl:apply-templates/>
</xsl:template>

<xsl:template match="level">
<xsl:fullPath select="concat('c',../@id,'_l',@id)"/>
<thisLevel uid="{$fullPath}"/>
<xsl:apply-templates/>
</xsl:template>

<xsl:template match="room">
<xsl:fullPath select="concat('c',../../@id,'_l',../@id,'_r',@id)"/>
<thisRoom uid="{$fullPath}"/>
<xsl:apply-templates/>
</xsl:template>

I'm guessing this is very inefficient, accessing the castle ID for each
room. is there a better way? I could generate an ID, but would the ID
reflect the data path it took to get to a particular room?

cheers

shaun
 
M

Martin Honnen

shaun roe wrote:

I'm guessing this is very inefficient, accessing the castle ID for each
room. is there a better way?

Well if you know that is the root element then a global variable
<xsl:variable name="rootId" select="/castle/@id" />
is all you need, then in your expressions you can use
$rootId
 
S

shaun roe

Martin Honnen said:
shaun roe wrote:



Well if you know that is the root element then a global variable
<xsl:variable name="rootId" select="/castle/@id" />
is all you need, then in your expressions you can use
$rootId

True, but accessing the root element multiple times is only the worst
symptom of my philosophy... each 'parent' Id gets recalled by each of
its children, each grandparent by both the children and grandchildren
etc. Maybe this is equally efficient as the nested template-call,
(passing the id as a parameter to children) if this information is
somehow cached... I dont know.
 
D

Dimitre Novatchev

The following transformation implements all your requirements:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:eek:utput omit-xml-declaration="yes" indent="yes"/>

<xsl:strip-space elements="*"/>

<xsl:template match="node()|@*">
<xsl:copy>
<xsl:attribute name="globalId">id<xsl:text/>
<xsl:number count="*" level="multiple"/>
</xsl:attribute>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

When applied on the source xml provided in your post, the result is:

<castle globalId="id1" id="0">
<level globalId="id1.1" id="2">
<room globalId="id1.1.1" id="2"/>
<room globalId="id1.1.2" id="3"/>
<room globalId="id1.1.3" id="4"/>
</level>
<level globalId="id1.2" id="3">
<room globalId="id1.2.1" id="2"/>
<room globalId="id1.2.2" id="3"/>
<room globalId="id1.2.3" id="4"/>
</level>
</castle>


Cheers,
Dimitre Novatchev
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,044
Latest member
RonaldNen

Latest Threads

Top