Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   XML (http://www.velocityreviews.com/forums/f32-xml.html)
-   -   count recursiv name-templated calls (http://www.velocityreviews.com/forums/t958101-count-recursiv-name-templated-calls.html)

Philipp Kraus 02-26-2013 05:25 PM

count recursiv name-templated calls
 
Hello,

I would like to work with XSLT (2.0). I have got code like

<xsl:template name="item">
<xsl:text>?? test</xsl:text>
</xsl:template>


and different matches in another file

<xsl:template match="node1"
<xsl:call-template name="item"/>
</xsl:template>

<xsl:template match="node2"
<xsl:call-template name="item"/>
</xsl:template>

my XML document shows eg

<node1>
</node1>

<node1>
<node2>
<node1/>
</node2>
</node1>

I would like to push the number of the recursiv-template matches of the
item template
on the position of ??. In the example XML I will get the numbers 1, 1, 2, 3
The item template should count itself the number of its recursiv calls

Thanks a lot

Phil


Joe Kesselman 02-26-2013 06:08 PM

Re: count recursiv name-templated calls
 
On 2/26/2013 12:25 PM, Philipp Kraus wrote:
> <xsl:text>?? test</xsl:text>


> I would like to push the number of the recursiv-template matches of the
> item template
> The item template should count itself the number of its recursiv calls


http://www.w3.org/TR/xslt20/#parameters

(That's supported in XSLT 1.0 as well, of course.)

Note that it's your responsibility to explicitly pass the parameter
value down the template call/apply tree.

I haven't checked, but examples can be undoubtedly be found at
http://www.dpawson.co.uk/xsl/sect2/N5982.html

For other kinds of counting, see
http://www.dpawson.co.uk/xsl/sect2/N2018.html

--
Joe Kesselman,
http://www.love-song-productions.com...lam/index.html

{} ASCII Ribbon Campaign | "may'ron DaroQbe'chugh vaj bIrIQbej" --
/\ Stamp out HTML mail! | "Put down the squeezebox & nobody gets hurt."

Philipp Kraus 02-26-2013 06:33 PM

Re: count recursiv name-templated calls
 
On 2013-02-26 19:08:41 +0100, Joe Kesselman said:

> On 2/26/2013 12:25 PM, Philipp Kraus wrote:
>> <xsl:text>?? test</xsl:text>

>
>> I would like to push the number of the recursiv-template matches of the
>> item template
>> The item template should count itself the number of its recursiv calls

>
> http://www.w3.org/TR/xslt20/#parameters
>
> (That's supported in XSLT 1.0 as well, of course.)
>
> Note that it's your responsibility to explicitly pass the parameter
> value down the template call/apply tree.
>
> I haven't checked, but examples can be undoubtedly be found at
> http://www.dpawson.co.uk/xsl/sect2/N5982.html
>
> For other kinds of counting, see
> http://www.dpawson.co.uk/xsl/sect2/N2018.html


I have found the "tunnel" argument on the template, IMHO this can count
the template calls,
so I have modified my template to

<xsl:template name="item">
<xsl:param name="depth" select="$depth+1" tunnel="yes"/>
<xsl:value-of select="$deph"/>
<xsl:text> test</xsl:text>
</xsl:template>

so now I get the error, that depth is not initialized. How can I
initialize and increment
the tunnel parameter?

Phil


Philipp Kraus 02-26-2013 10:35 PM

Re: count recursiv name-templated calls
 
On 2013-02-26 19:08:41 +0100, Joe Kesselman said:

> On 2/26/2013 12:25 PM, Philipp Kraus wrote:
>> <xsl:text>?? test</xsl:text>

>
>> I would like to push the number of the recursiv-template matches of the
>> item template
>> The item template should count itself the number of its recursiv calls

>
> http://www.w3.org/TR/xslt20/#parameters
>
> (That's supported in XSLT 1.0 as well, of course.)
>
> Note that it's your responsibility to explicitly pass the parameter
> value down the template call/apply tree.
>
> I haven't checked, but examples can be undoubtedly be found at
> http://www.dpawson.co.uk/xsl/sect2/N5982.html
>
> For other kinds of counting, see
> http://www.dpawson.co.uk/xsl/sect2/N2018.html


I have got some problems to modify the code.
I have a complex XSL file, in which are a lot of apply templates and a lot of
call of my "item" template.

I must create a plain text structure

# section1
## section 2
### section 3

# section 4

On each call of my item template a counter must be increment, that counts the
recursiv calls of the item template. Different XML nodes can be call
the item template
from different nodes on the XSL document, so IMHO the best solution is
that my item
template counts the recursiv calls.
I can not use the XML structure, because my template calls are
different because in some case
if / chose calls are enable / disable the item template call.

Phil


Alain Ketterlin 02-27-2013 10:30 AM

Re: count recursiv name-templated calls
 
Philipp Kraus <philipp.kraus@flashpixx.de> writes:

> On 2013-02-26 19:08:41 +0100, Joe Kesselman said:
>
>> On 2/26/2013 12:25 PM, Philipp Kraus wrote:
>>
>>> I would like to push the number of the recursiv-template matches of
>>> the item template The item template should count itself the number
>>> of its recursiv calls

>>
>> http://www.w3.org/TR/xslt20/#parameters

[...]

> I have found the "tunnel" argument on the template,


Note to self: Oh my God... dynamic scoping in XSLT. It's turning mad...

> IMHO this can count the template calls, so I have modified my template
> to
>
> <xsl:template name="item">
> <xsl:param name="depth" select="$depth+1" tunnel="yes"/>
> <xsl:value-of select="$deph"/>
> <xsl:text> test</xsl:text>
> </xsl:template>


select provides a default value, in case none is passed. So this won't
work.

You haven't shown us how you call the templates on node1 or node2.
That's where all the work would go. AFAIU there is no need of tunneling
here, or at least tunneling doesn't fit your requirements (tunnel just
passes the values, you need them to be incremented).

So, how do the recursive calls happen? In the following, I assume you
have something like that:

<xsl:template match="node1">
<xsl:call-template name="item" select="."/>
<xsl:apply-templates select="*"/> <!-- recurse -->
</xsl:template>

and the same for node2 (or match="node1|node2" on this template).

Now let's add the "depth" parameter:

<xsl:template match="node1">
<xsl:param name="depth" select="0"/>
<xsl:call-template name="item" select=".">
<xsl:with-param name="depth" select="$depth"/>
</xsl:call-template>
<xsl:apply-templates select="*">
<xsl:with-param name="depth" select="$depth+1"/>
</xsl:template>
</xsl:template>

Note that select is used to provide zero if no parameter is passed to
the "node1" template". This does the initialization. Of course you're
free to pass whatever else you want (which is what happens for the
potentially recursive calls done by <xsl:apply-templates>).

AFAIU, using tunneling could save the first <xsl:with-param>. I'm not
sure this is worth the trouble; you decide.

BTW, if you want to know how many node1 or node2 are above the current
node, you can use:

<xsl:value-of
select="count(ancestor::*[name()="node1" or name()="node2"])"/>

or

<xsl:value-of select="count(ancestor::node1)+count(ancestor::nod e2)"/>

This is off by 1, use ancestor-or-self to consider also the current
node. It also assumes no namespace is in use.

-- Alain.

Martin Honnen 02-27-2013 11:00 AM

Re: count recursiv name-templated calls
 
Alain Ketterlin wrote:

> So, how do the recursive calls happen? In the following, I assume you
> have something like that:
>
> <xsl:template match="node1">
> <xsl:call-template name="item" select="."/>
> <xsl:apply-templates select="*"/> <!-- recurse -->
> </xsl:template>
>
> and the same for node2 (or match="node1|node2" on this template).
>
> Now let's add the "depth" parameter:
>
> <xsl:template match="node1">
> <xsl:param name="depth" select="0"/>
> <xsl:call-template name="item" select=".">
> <xsl:with-param name="depth" select="$depth"/>
> </xsl:call-template>


I am confused, since then does "call-template" take a "select" attribute?

http://www.w3.org/TR/xslt20/#named-templates does not show any.


Alain Ketterlin 02-27-2013 11:25 AM

Re: count recursiv name-templated calls
 
Martin Honnen <mahotrash@yahoo.de> writes:

> Alain Ketterlin wrote:


>> <xsl:template match="node1">
>> <xsl:param name="depth" select="0"/>
>> <xsl:call-template name="item" select=".">
>> <xsl:with-param name="depth" select="$depth"/>
>> </xsl:call-template>

>
> I am confused, since then does "call-template" take a "select"
> attribute?


You know the answer: I've just invented this nonsense. Even if it
existed it would be useless anyway since call-template doesn't change
the current node.

-- Alain.

Philipp Kraus 02-27-2013 02:06 PM

Re: count recursiv name-templated calls
 
On 2013-02-27 11:30:34 +0100, Alain Ketterlin said:

> Philipp Kraus <philipp.kraus@flashpixx.de> writes:
>
>> On 2013-02-26 19:08:41 +0100, Joe Kesselman said:
>>
>>> On 2/26/2013 12:25 PM, Philipp Kraus wrote:
>>>
>>>> I would like to push the number of the recursiv-template matches of
>>>> the item template The item template should count itself the number
>>>> of its recursiv calls
>>>
>>> http://www.w3.org/TR/xslt20/#parameters

> [...]
>
>> I have found the "tunnel" argument on the template,

>
> Note to self: Oh my God... dynamic scoping in XSLT. It's turning mad...
>
>> IMHO this can count the template calls, so I have modified my template
>> to
>>
>> <xsl:template name="item">
>> <xsl:param name="depth" select="$depth+1" tunnel="yes"/>
>> <xsl:value-of select="$deph"/>
>> <xsl:text> test</xsl:text>
>> </xsl:template>

>
> select provides a default value, in case none is passed. So this won't
> work.
>
> You haven't shown us how you call the templates on node1 or node2.
> That's where all the work would go. AFAIU there is no need of tunneling
> here, or at least tunneling doesn't fit your requirements (tunnel just
> passes the values, you need them to be incremented).


Yes, I have seen at night. I have found a working solution

http://saxon.sourceforge.net/saxon7....tml#assignable

so I can do this
<xsl:variable name="listindent" select="0" as="xs:integer"
saxon:assignable="yes"/>

<xsl:template name="listitem">
<xsl:param name="value"/>
<xsl:param name="item" select="'*'"/>

<xsl:call-template name="listindent"/>
<saxon:assign name="listindent" select="$listindent+1"/>

<xsl:value-of select="$item"/>
<xsl:text> </xsl:text>
<xsl:value-of select="$value"/>
<xsl:call-template name="nl"/>

<saxon:assign name="listindent" select="-1+$listindent"/>
</xsl:template>

If the $value also a listitem, the listindent stores the correct value,
but it is a non-generic

Phil


Philipp Kraus 02-28-2013 01:14 AM

Re: count recursiv name-templated calls
 
On 2013-02-27 11:30:34 +0100, Alain Ketterlin said:

> Philipp Kraus <philipp.kraus@flashpixx.de> writes:
>
>> On 2013-02-26 19:08:41 +0100, Joe Kesselman said:
>>
>>> On 2/26/2013 12:25 PM, Philipp Kraus wrote:
>>>
>>>> I would like to push the number of the recursiv-template matches of
>>>> the item template The item template should count itself the number
>>>> of its recursiv calls
>>>
>>> http://www.w3.org/TR/xslt20/#parameters

> [...]


[...]

>
> <xsl:template match="node1">
> <xsl:param name="depth" select="0"/>
> <xsl:call-template name="item" select=".">
> <xsl:with-param name="depth" select="$depth"/>
> </xsl:call-template>
> <xsl:apply-templates select="*">
> <xsl:with-param name="depth" select="$depth+1"/>
> </xsl:template>
> </xsl:template>
>
> Note that select is used to provide zero if no parameter is passed to
> the "node1" template". This does the initialization. Of course you're
> free to pass whatever else you want (which is what happens for the
> potentially recursive calls done by <xsl:apply-templates>).


This would be my first try but I have posted a short example of my problem.
The calls for the "item" template are within another XSL file, which can not be
changed (at the moment), so I can modify only the item template and need
the depth counter in this template.

With your solution i must modify each item call and each apply call, is
this correct?
But in this way on each apply the depth counter will be increment, or does it?
So $depth stores not the recursion depth of item but rather the depth
of the apply calls,
do I understand it correct?


> BTW, if you want to know how many node1 or node2 are above the current
> node, you can use:
>
> <xsl:value-of
> select="count(ancestor::*[name()="node1" or name()="node2"])"/>
>
> or
>
> <xsl:value-of select="count(ancestor::node1)+count(ancestor::nod e2)"/>


If I understand it correct, this value returns the depth of the "node
recursion of my XML tree".

In my problem, I want to count the recursiv call of a single template
here item, so if the parser
runs over my XML nodes and calls the item template and within the
descent of the XML node item
again, I will get the value 2, because item is recursive called twice.

Phil


Joe Kesselman 02-28-2013 03:09 AM

Re: count recursiv name-templated calls
 
On 2/27/2013 8:14 PM, Philipp Kraus wrote:
> If I understand it correct, this value returns the depth of the "node
> recursion of my XML tree".
> In my problem, I want to count the recursiv call of a single template


That was my understanding, which is why I pointed you to parameters.

Many "counting" tasks in XSLT really are better handled by using the
numbering facilities designed into the language -- but those are
generally focused on enumerating positions in the document tree rather
than call depth, so they wouldn't have been the right answer for the
question you asked.

--
Joe Kesselman,
http://www.love-song-productions.com...lam/index.html

{} ASCII Ribbon Campaign | "may'ron DaroQbe'chugh vaj bIrIQbej" --
/\ Stamp out HTML mail! | "Put down the squeezebox & nobody gets hurt."


All times are GMT. The time now is 08:00 AM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.