How often is my recursive template called ??

R

Rolf Kemper

Dear All,

somehow I remember that such or similar question was discussed already
somewhere. But I can't find it anymore.

I have a template calling itself. As long it goes deeper into the
hierarchy (by the key) I can set the CurrentY parameter by itself +
some constant correctly. Hence which each call the CurrentY gets
bigger.
But when the template reaches a leave and the caller is poped from
stack the old parameter is valid. Hence the absolute sum is lost.

Finally, as a minimun information, I would like to know how often the
recursive template has been called at all (at any time during
recursive execution).

Please find below a xslt which outputs svg rectangles with some text
(the OrgaID) Actually it should draw many rectangles, but as the
currentY is not computed correctly the rectangles overlap and we see
only 5 (which is determined by the maximum hierarchy depth) .

Any hint and help is highly welcome

Rolf

################## xslt ####################################
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:a3="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"<xsl:eek:utput method="xml" version="1.0" encoding="UTF-8"
indent="yes"/>
<xsl:key name="kOrga" match="/Orga/OrgaBox" use="@BelongsTo"/>
<xsl:template match="/">
<svg contentScriptType="text/ecmascript" width="500" height="500"
viewBox="0 0 10000 30000" a3:scriptImplementation="Adobe"
zoomAndPan="magnify" contentStyleType="text/css" id="PinFunction"
preserveAspectRatio="xMidYMid meet">
<g id="all" transform="translate(2000,2000)">
<xsl:apply-templates select="/Orga/OrgaBox[@OrgaID=169]"/><!--
this is the top one -->
</g>
</svg>
</xsl:template>

<xsl:template name="BuildBoxes" match="*">
<xsl:param name="CurrentX" select="0"/>
<xsl:param name="CurrentY" select="0"/>
<g>
<xsl:attribute name="transform"><xsl:value-of
select="concat('translate(',$CurrentX,',',$CurrentY,')')"/></xsl:attribute>
<rect style="fill:yellow;stroke:red;stroke-width:10" width="5000"
height="2000"/>
<text x="200" y="1000" pointer-events="none"
style="fill:black;font-size:800">
<xsl:value-of select="@OrgaID"/>
</text>
</g>
<xsl:apply-templates select="key('kOrga',@OrgaID)">
<xsl:with-param name="CurrentY" select="$CurrentY+3000"/>
</xsl:apply-templates>
</xsl:template>
</xsl:stylesheet>

######## xml test data ###########################################
<?xml version="1.0" encoding="UTF-8"?>
<Orga>
<OrgaBox OrgaID="131" BelongsTo="169" />
<OrgaBox OrgaID="132" BelongsTo="135" />
<OrgaBox OrgaID="133" BelongsTo="169" />
<OrgaBox OrgaID="135" BelongsTo="169" />
<OrgaBox OrgaID="136" BelongsTo="169" />
<OrgaBox OrgaID="137" BelongsTo="171" />
<OrgaBox OrgaID="138" BelongsTo="171" />
<OrgaBox OrgaID="139" BelongsTo="171" />
<OrgaBox OrgaID="140" BelongsTo="171" />
<OrgaBox OrgaID="141" BelongsTo="136" />
<OrgaBox OrgaID="142" BelongsTo="132" />
<OrgaBox OrgaID="143" BelongsTo="135" />
<OrgaBox OrgaID="144" BelongsTo="135" />
<OrgaBox OrgaID="145" BelongsTo="143" />
<OrgaBox OrgaID="146" BelongsTo="132" />
<OrgaBox OrgaID="147" BelongsTo="133" />
<OrgaBox OrgaID="148" BelongsTo="162" />
<OrgaBox OrgaID="149" BelongsTo="139" />
<OrgaBox OrgaID="150" BelongsTo="139" />
<OrgaBox OrgaID="151" BelongsTo="139" />
<OrgaBox OrgaID="155" BelongsTo="182" />
<OrgaBox OrgaID="156" BelongsTo="136" />
<OrgaBox OrgaID="157" BelongsTo="139" />
<OrgaBox OrgaID="158" BelongsTo="136" />
<OrgaBox OrgaID="159" BelongsTo="133" />
<OrgaBox OrgaID="160" BelongsTo="137" />
<OrgaBox OrgaID="161" BelongsTo="138" />
<OrgaBox OrgaID="162" BelongsTo="138" />
<OrgaBox OrgaID="163" BelongsTo="138" />
<OrgaBox OrgaID="164" BelongsTo="139" />
<OrgaBox OrgaID="165" BelongsTo="139" />
<OrgaBox OrgaID="166" BelongsTo="140" />
<OrgaBox OrgaID="167" BelongsTo="140" />
<OrgaBox OrgaID="168" BelongsTo="140" />
<OrgaBox OrgaID="169" BelongsTo="0" />
<OrgaBox OrgaID="170" BelongsTo="169" />
<OrgaBox OrgaID="171" BelongsTo="169" />
<OrgaBox OrgaID="172" BelongsTo="169" />
<OrgaBox OrgaID="174" BelongsTo="182" />
<OrgaBox OrgaID="175" BelongsTo="138" />
<OrgaBox OrgaID="182" BelongsTo="136" />
<OrgaBox OrgaID="192" BelongsTo="132" />
</Orga>

################ END #####################################
 
J

Joris Gillis

I have a template calling itself. As long it goes deeper into the
hierarchy (by the key) I can set the CurrentY parameter by itself +
some constant correctly. Hence which each call the CurrentY gets
bigger.
But when the template reaches a leave and the caller is poped from
stack the old parameter is valid. Hence the absolute sum is lost.

Finally, as a minimun information, I would like to know how often the
recursive template has been called at all (at any time during
recursive execution).

Please find below a xslt which outputs svg rectangles with some text
(the OrgaID) Actually it should draw many rectangles, but as the
currentY is not computed correctly the rectangles overlap and we see
only 5 (which is determined by the maximum hierarchy depth) .

Any hint and help is highly welcome

Hi,

As far as I know, there's no way to find out how many times a template is called in XSLT. To solve your specific problem, I think you have to do 2 transformations (2 consecutive transformations or the use of a document fragment node).

Using the following template, a node tree is generated that will be easier to transform to the desired SVG:

<xsl:template name="BuildBoxes" match="*">
<box caption="{@OrgaID}">
<xsl:apply-templates select="key('kOrga',@OrgaID)"/>
</box>
</xsl:template>


## output snippet ###

<box caption="131"/>
<box caption="133">
<box caption="147"/>
<box caption="159"/>
</box>
<box caption="135">
<box caption="132">
<box caption="142"/>
<box caption="146"/>
<box caption="192"/>
</box>
<box caption="143">
<box caption="145"/>
</box>
<box caption="144"/>
</box>


regards,
 
J

Joris Gillis

<box caption="131"/>
<box caption="133">
<box caption="147"/>
<box caption="159"/>
</box>
<box caption="135">
<box caption="132">
<box caption="142"/>
<box caption="146"/>
<box caption="192"/>
</box>
<box caption="143">
<box caption="145"/>
</box>
<box caption="144"/>
</box>

Applying the following stylesheet on the output above, would display structured SVG.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:a3="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"<xsl:eek:utput method="xml" version="1.0" encoding="UTF-8"
indent="yes"/>
<xsl:key name="kOrga" match="/Orga/OrgaBox" use="@BelongsTo"/>
<xsl:template match="/">
<svg contentScriptType="text/ecmascript" width="500" height="500"
viewBox="0 0 10000 30000" a3:scriptImplementation="Adobe"
zoomAndPan="magnify" contentStyleType="text/css" id="PinFunction"
preserveAspectRatio="xMidYMid meet">
<defs>
<style type="text/css">
rect {fill:yellow;stroke:red;stroke-width:10}
text {fill:black;font-size:800}
</style>
</defs>
<g id="all" transform="translate(2000,2000)">
<xsl:apply-templates select="box"/>
</g>
</svg>
</xsl:template>

<xsl:template match="box">
<g>
<xsl:attribute name="transform"><xsl:value-of
select="concat('translate(',count(ancestor::*) * 8000 ,',',count(preceding::*)*3000,')')"/></xsl:attribute>
<rect width="5000"
height="2000"/>
<text x="200" y="1000" pointer-events="none">
<xsl:value-of select="@caption"/>
</text>
</g>
<xsl:apply-templates select="box"/>
</xsl:template>


</xsl:stylesheet>
 
R

Rolf Kemper

Dear Joris,

thanks a lot for your input.
I think you idea is the only practical solution. But as I undestood it
right I have to store the 'converted' result set first to a file. I
would like to aviod that and tried to create a variable which should
fianlly hold the pre-processed data as an xml tree. Aftrer that I
would like to process this variable.

I tried the snipet below with XMLSpy (ALTOVA). In debug mode the
result of the variable is shown as Caption="169" Box="" Box="" Box=""
Box="" Box="" Box="" Box="" Which indicates that the tree is not build
correctly.
What I'm doing wrong ?
I expected a hirarchial tree of Box Elements with one Attribute
Caption for each element.

May be my idea to create a tree in a variable and then process it is
bad at all.
But if there is a solution, it has probably a lot of applications.

Looking forward to your comments/inputs

Rolf


################### snipet ####################################
<xsl:template match="/">
<xsl:variable name="vProtoBoxes">
<xsl:apply-templates mode="PROTO"
select="/Orga/OrgaBox[@OrgaID=169]"/>
</xsl:variable>
<svg contentScriptType="text/ecmascript" width="500" height="500"
viewBox="0 0 10000 30000" a3:scriptImplementation="Adobe"
zoomAndPan="magnify" contentStyleType="text/css" id="PinFunction"
preserveAspectRatio="xMidYMid meet">
<g id="all" transform="translate(2000,2000)">
<!-- ... processing the varaiable follows here -->
</g>
</svg>
</xsl:template>

<xsl:template mode="PROTO" name="BuildProtoBoxes" match="*">
<xsl:element name="Box">
<xsl:attribute name="Caption">
<xsl:value-of select="@OrgaID"/>
</xsl:attribute>
<xsl:apply-templates mode="PROTO" select="key('kOrga',@OrgaID)"/>
</xsl:element>
</xsl:template>


##################### end of snipet #################################
 
J

Joris Gillis

Hi again,
I tried the snipet below with XMLSpy (ALTOVA). In debug mode the
result of the variable is shown as Caption="169" Box="" Box="" Box=""
Box="" Box="" Box="" Box="" Which indicates that the tree is not build
correctly.
What I'm doing wrong ?

Your code generates a variable with exactly the tree you want. (using altovaxslt.exe). The only explaination I can see, is that the debug mode of XMLSpy doesn't show the exact XML-tree but rather a more textual representation. The 'Box' elements contain no text-nodes, so the debugger might indicate that with 'Box=""' . Perhaps you can change some configurations of the program to see the XML-tree.

You could try the 'box' template in my 2nd mail to test if the variable contains the right xml-tree. (the case of the element names should be updated).
May be my idea to create a tree in a variable and then process it is
bad at all.

Off course it's not bad. With 'document fragment node' (in my first mail) I actually meant using a variable to store the 'pre-processed xml tree'.


Don't hesitate to post further questions or remarks.

regards,
 
R

Rolf Kemper

Hi Joris,

thank you very much for your confirmation.
I have tried to combine our code, but I get still stuck at using the
variable which should hold the tree/tree fragment or whatever this is
called correctly. Using the variable in the select part of an
apply-templates element leads to the following error (in debug mode,
menas xmlspy processor):
"Cannot use result tree fragmentError in Xpath expression, Cannot use
result tree fragment"

Using MSXML4 I get:

"Expression must evaluate to a node-set
->$vOrgaTree<- "


I tried to get some answers by the debugger (xpath evaluation after
break) gambling with $vOrgaTree/* , $vOrgaTree/self::* ...

I have also tried to add a top element(to make the tree well formed in
sense of xml)
But all this never lead to a good result !!!

I think my basic understanding of node-set and result tree fragment is
still zero.

Please find below my xslt trial (combined code from both of us)


Thanks a lot for your help
(I feel still like a very beginner in xslt as you see)

######### xslt ########################################
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:a3="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/">
<xsl:eek:utput method="xml" version="1.0" encoding="UTF-8"
indent="yes"/>


<xsl:key name="kOrga" match="/Orga/OrgaBox" use="@BelongsTo"/>

<xsl:template mode="PROTO" name="BuildProtoBoxes" match="*">
<xsl:element name="box">
<xsl:attribute name="caption">
<xsl:value-of select="@OrgaID"/>
</xsl:attribute>
<xsl:apply-templates mode="PROTO" select="key('kOrga',@OrgaID)"/>
</xsl:element>
</xsl:template>

<xsl:template match="/">
<xsl:variable name="vOrgaTree" >
<xsl:apply-templates mode="PROTO" select="key('kOrga','169')"/>
</xsl:variable>
<xsl:value-of select="$vOrgaTree"></xsl:value-of><!-- just for test
and break point setting -->
<xsl:apply-templates mode="SVG" select="$vOrgaTree"/><!-- the error
happens here !!! -->
</xsl:template>

<xsl:template mode="SVG" match="/">
<svg contentScriptType="text/ecmascript" width="500" height="500"
viewBox="0 0 10000 30000" a3:scriptImplementation="Adobe"
zoomAndPan="magnify" contentStyleType="text/css" id="PinFunction"
preserveAspectRatio="xMidYMid meet">
<defs>
<style type="text/css">
rect {fill:yellow;stroke:red;stroke-width:10}
text {fill:black;font-size:800}
</style>
</defs>
<g id="all" transform="translate(2000,2000)">
<xsl:apply-templates select="box"/>
</g>
</svg>
</xsl:template>
<xsl:template match="box">
<g>
<xsl:attribute name="transform"><xsl:value-of
select="concat('translate(',count(ancestor::*) * 8000
,',',count(preceding::*)*3000,')')"/></xsl:attribute>
<rect width="5000" height="2000"/>
<text x="200" y="1000" pointer-events="none">
<xsl:value-of select="@caption"/>
</text>
</g>
<xsl:apply-templates select="box"/>
</xsl:template>

</xsl:stylesheet>
######################### xml just for reference as you may have it
already ###
<?xml version="1.0" encoding="UTF-8"?>
<Orga>
<OrgaBox OrgaID="131" BelongsTo="169" />
<OrgaBox OrgaID="132" BelongsTo="135" />
<OrgaBox OrgaID="133" BelongsTo="169" />
<OrgaBox OrgaID="135" BelongsTo="169" />
<OrgaBox OrgaID="136" BelongsTo="169" />
<OrgaBox OrgaID="137" BelongsTo="171" />
<OrgaBox OrgaID="138" BelongsTo="171" />
<OrgaBox OrgaID="139" BelongsTo="171" />
<OrgaBox OrgaID="140" BelongsTo="171" />
<OrgaBox OrgaID="141" BelongsTo="136" />
<OrgaBox OrgaID="142" BelongsTo="132" />
<OrgaBox OrgaID="143" BelongsTo="135" />
<OrgaBox OrgaID="144" BelongsTo="135" />
<OrgaBox OrgaID="145" BelongsTo="143" />
<OrgaBox OrgaID="146" BelongsTo="132" />
<OrgaBox OrgaID="147" BelongsTo="133" />
<OrgaBox OrgaID="148" BelongsTo="162" />
<OrgaBox OrgaID="149" BelongsTo="139" />
<OrgaBox OrgaID="150" BelongsTo="139" />
<OrgaBox OrgaID="151" BelongsTo="139" />
<OrgaBox OrgaID="155" BelongsTo="182" />
<OrgaBox OrgaID="156" BelongsTo="136" />
<OrgaBox OrgaID="157" BelongsTo="139" />
<OrgaBox OrgaID="158" BelongsTo="136" />
<OrgaBox OrgaID="159" BelongsTo="133" />
<OrgaBox OrgaID="160" BelongsTo="137" />
<OrgaBox OrgaID="161" BelongsTo="138" />
<OrgaBox OrgaID="162" BelongsTo="138" />
<OrgaBox OrgaID="163" BelongsTo="138" />
<OrgaBox OrgaID="164" BelongsTo="139" />
<OrgaBox OrgaID="165" BelongsTo="139" />
<OrgaBox OrgaID="166" BelongsTo="140" />
<OrgaBox OrgaID="167" BelongsTo="140" />
<OrgaBox OrgaID="168" BelongsTo="140" />
<OrgaBox OrgaID="169" BelongsTo="0" />
<OrgaBox OrgaID="170" BelongsTo="169" />
<OrgaBox OrgaID="171" BelongsTo="169" />
<OrgaBox OrgaID="172" BelongsTo="169" />
<OrgaBox OrgaID="174" BelongsTo="182" />
<OrgaBox OrgaID="175" BelongsTo="138" />
<OrgaBox OrgaID="182" BelongsTo="136" />
<OrgaBox OrgaID="192" BelongsTo="132" />
</Orga>

############## END ####################################








Joris Gillis said:
Hi again,


Your code generates a variable with exactly the tree you want.
(using altovaxslt.exe). The only explaination I can see, is that the
debug mode of XMLSpy doesn't show the exact XML-tree but rather a more
textual representation. The 'Box' elements contain no text-nodes, so
the debugger might indicate that with 'Box=""' . Perhaps you can
change some configurations of the program to see the XML-tree.
 
J

Joris Gillis

Using the variable in the select part of an
apply-templates element leads to the following error (in debug mode,
menas xmlspy processor):
"Cannot use result tree fragmentError in Xpath expression, Cannot use
result tree fragment"

Using MSXML4 I get:

"Expression must evaluate to a node-set
->$vOrgaTree<- "

Hi,

I forgot to tell: XSLT 1.0 doesn't allow the use of result tree fragments in XPATH expressions. It's only supported by version 1.1 . You must define this in the header:

<xsl:stylesheet version="1.1"/>

[
If the processor cannot handle XSLT 1.1, you must use an extension function like 'exsl:node-set()' , look for another processor or do the transformation with 2 seperate documents.
]

I hope you've not been spilling to much time or temper, trying to solve this issue.


regards,
 
D

David Carlisle

Joris Gillis said:
Hi,

I forgot to tell: XSLT 1.0 doesn't allow the use of result tree
fragments in XPATH expressions. It's only supported by version 1.1
. You must define this in the header:

<xsl:stylesheet version="1.1"/>

There is no XSLT 1.1 (and never will be) there was a working draft but
the working group explictly killed off work on 1.1 in order to work on
2.0. So it will only ever be a working draft and explictly should not be
cited, except as work (not now) in progress. Unfortunately a couple of
processors do still have experimental support for this draft but it
should not be relied on.
[
If the processor cannot handle XSLT 1.1, you must use an extension function like 'exsl:node-set()' , look for another processor or do the transformation with 2 seperate documents.
]

I hope you've not been spilling to much time or temper, trying to solve this issue.


regards,


msxml has a node-set extension function in its own extension namespace.

David
 

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,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top