468,168 Members | 1,494 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,168 developers. It's quick & easy.

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

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
Sep 28 '05 #1
3 2494


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

--

Martin Honnen
http://JavaScript.FAQTs.com/
Sep 28 '05 #2
In article <43***********************@newsread4.arcor-online.net>,
Martin Honnen <ma*******@yahoo.de> wrote:
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


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.
Sep 28 '05 #3
The following transformation implements all your requirements:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output 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
"shaun roe" <sh*******@wanadoo.fr> wrote in message
news:sh*****************************@news-reader.wanadooportails.com...
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

Sep 28 '05 #4

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

reply views Thread by Sergio del Amo | last post: by
1 post views Thread by Leo Kirch | last post: by
reply views Thread by Vincent Lefevre | last post: by
reply views Thread by Chris Young | last post: by
6 posts views Thread by Mike Grass | last post: by
4 posts views Thread by dwergkees | last post: by
1 post views Thread by notnorwegian | last post: by
3 posts views Thread by z1 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.