Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > XML > XSL -- Global Variables

Reply
Thread Tools

XSL -- Global Variables

 
 
Loopy
Guest
Posts: n/a
 
      11-02-2004
I'm learning XML and XSL at the moment, but I still can't get my head
around the concept of non-updatable variables. I know we can use
recursion to cycle through a data structure and get the sum (say) of a
list of numbers, or a concatination of a set of strings (again,
example), but if I wanted to, for example, keep that value available
for another template later on to use, I can't see how I could do that.

Let me give a better example. I have written and template which is
called "FindMin" that cycles through a tree that finds the minimum. I
have checked the code and, when it it does go through all of the
subtrees and finds the minimum. However, it will only find the minimum
of each of the subtrees, since I cannot keep a global track of the
smallest value, since when I propagate up the tree, I will lose that
value. How could I rectify this?

Here's the code I've written. It may be a bit crude, but that's
because I've been messing around with it. Min and Path are declared as
an empty string (Min) and the root node of the tree in question at
first call.

<xsl:template name="FindMin">
<xslaram name="Min"/>
<xslaram name="Path"/>
<xsl:for-each select="./*">
<xsl:choose>
<xsl:when test="@value &lt; $Min">
<!-- Call template with updated min and path -->
<xsl:call-template name="FindMin">
<xsl:with-param name="Min" select="@value"/>
<xsl:with-param name="Path" select="."/>
</xsl:call-template>
</xsl:when>
<xsltherwise>
<!-- Call template with updated path only -->
<xsl:call-template name="FindMin">
<xsl:with-param name="Min" select="$Min"/>
<xsl:with-param name="Path" select="."/>
</xsl:call-template>
</xsltherwise>
</xsl:choose>
</xsl:for-each>


The tree I am using for this test is:

<node value="10">
<node value="15"/>
<node value="5">
<node value="7">
<node value="9"/>
<node value="8"/>
</node>
<node value="11"/>
</node>
</node>

Any ideas any one? I'm sure you've had this question before, but most
answers I've checked seem to use Microsoft's XML variation, which I'm
trying to avoid.

Regards

Johnny Ooi
 
Reply With Quote
 
 
 
 
Joris Gillis
Guest
Posts: n/a
 
      11-03-2004
On 2 Nov 2004 12:20:41 -0800, Loopy <> wrote:

> I'm learning XML and XSL at the moment, but I still can't get my head
> around the concept of non-updatable variables. I know we can use
> recursion to cycle through a data structure and get the sum (say) of a
> list of numbers, or a concatination of a set of strings (again,
> example), but if I wanted to, for example, keep that value available
> for another template later on to use, I can't see how I could do that.
>
> Let me give a better example. I have written and template which is
> called "FindMin" that cycles through a tree that finds the minimum. I
> have checked the code and, when it it does go through all of the
> subtrees and finds the minimum. However, it will only find the minimum
> of each of the subtrees, since I cannot keep a global track of the
> smallest value, since when I propagate up the tree, I will lose that
> value. How could I rectify this?
>
> Here's the code I've written. It may be a bit crude, but that's
> because I've been messing around with it. Min and Path are declared as
> an empty string (Min) and the root node of the tree in question at
> first call.


Hi,

Variables or parameters are indeed non-updateble in XSLT 1.0 and AFAIK there's nothing you can do about. But often, you can get around it by carefully overthinking the problem and redesigning the solution. Encapsulating 'xsl:call-template' with a variable might bring a solution in some cases.

I know that finding a solution to your specific example problem is not the reason for your post, but I'll put my solution here nonetheless:

<xsl:template name="FindMin">
<xslaram name="Min">9999</xslaram>
<xsl:choose>
<xsl:when test="count(//*[@value &lt; $Min]) &gt; 0">
<xsl:call-template name="FindMin">
<xsl:with-param name="Min" select="//*[@value &lt; $Min]/@value"/>
</xsl:call-template>
</xsl:when>
<xsltherwise>
<xsl:value-of select="$Min"/>
</xsltherwise>
</xsl:choose>
</xsl:template>


regards,

--
Joris Gillis (http://www.ticalc.org/cgi-bin/acct-v...i?userid=38041)
Ceterum censeo XML omnibus esse utendum
 
Reply With Quote
 
 
 
 
Johnny Ooi
Guest
Posts: n/a
 
      11-03-2004



Thanks for the code, it does the job. Two questions. First, if I wanted
to pass this to another template, I would place a call to the template
in the <xsltherwise> tag, correct? Second, could you step through the
code for me so I understand how the execution flows through. I'm using
the XSLT engine provided by Altova and that doesn't exactly provide a
friendly debug environment.

Johnny

*** Sent via Developersdex http://www.developersdex.com ***
Don't just participate in USENET...get rewarded for it!
 
Reply With Quote
 
Joris Gillis
Guest
Posts: n/a
 
      11-03-2004
Hi,

> Thanks for the code, it does the job. Two questions. First, if I wanted
> to pass this to another template, I would place a call to the template
> in the <xsltherwise> tag, correct?


You could, But I wouldn't do that.
I would use:

<xsl:variable name="Minimum">
<xsl:call-template name="FindMin"/>
</xsl:variable>

<xsl:call-template name="do-something">
<xsl:with-param name="parameter" select="$Minimum"/>
</xsl:call-template>

Or, if the minimum's only purpose is being fed to another template ,I'd prefer to use:

<xsl:call-template name="do-something">
<xsl:with-param name="parameter">
<xsl:call-template name="FindMin"/>
</xsl:with-param>
</xsl:call-template>


> Second, could you step through the
> code for me so I understand how the execution flows through. I'm using
> the XSLT engine provided by Altova and that doesn't exactly provide a
> friendly debug environment.


<xsl:template name="FindMin">
<!-- if the param 'Min' is empty, give it some 'value' attribute (It doesn't matter from which node it comes) -->
<xslaram name="Min"><xsl:value-of select="//@value"/></xslaram>
<xsl:choose>
<xsl:when test="count(//*[@value &lt; $Min]) &gt; 0">
<!-- if the current node has any descendants with a 'value' attribute smaller than the current minimum -->
<!-- call this template again with a 'Min' parameter that is equal to the first 'value' attribute smaller than the current Minimum -->
<xsl:call-template name="FindMin">
<!-- the current node remains the same: we don't plunge into the tree -->
<xsl:with-param name="Min" select="//*[@value &lt; $Min]/@value"/>
</xsl:call-template>
</xsl:when>
<xsltherwise>
<!-- if the tree has no such descendents (i.e. the Minimum is found), display the Minimum -->
<!-- the template has done it's job and all recursively called templates above will close silently-->
<xsl:value-of select="$Min"/>
</xsltherwise>
</xsl:choose>
</xsl:template>

Btw, I don't have any debug environment.

Hope this helps.


regards,
--
Joris Gillis (http://www.ticalc.org/cgi-bin/acct-v...i?userid=38041)
Ceterum censeo XML omnibus esse utendum
 
Reply With Quote
 
Johnny Ooi
Guest
Posts: n/a
 
      11-03-2004
Wow, so I didn't need to worry about doing all those recursive calls, I
could have used the "//" selector instead. So this selects all
decendents at all levels, is that right?




*** Sent via Developersdex http://www.developersdex.com ***
Don't just participate in USENET...get rewarded for it!
 
Reply With Quote
 
Joris Gillis
Guest
Posts: n/a
 
      11-03-2004
> Wow, so I didn't need to worry about doing all those recursive calls, I
> could have used the "//" selector instead. So this selects all
> decendents at all levels, is that right?


That's coorect. ('//' is short for '/descendant-or-self::node()/')

But one could argue if this Xpath approach is better than using recursive calls.

regards,
--
Joris Gillis (http://www.ticalc.org/cgi-bin/acct-v...i?userid=38041)
Ceterum censeo XML omnibus esse utendum
 
Reply With Quote
 
Johnny Ooi
Guest
Posts: n/a
 
      11-04-2004



Thanks for that, I'm going to go play with that and see what I can make
of it.

Johnny

*** Sent via Developersdex http://www.developersdex.com ***
Don't just participate in USENET...get rewarded for it!
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Initialize global variable before any other global variables jubelbrus C++ 5 07-20-2007 06:38 PM
FWSM/PIX and Dynamic PAT using global IP range vs. global interface vs. global IP Hoffa Cisco 1 10-25-2006 06:50 PM
FWSM/PIX and Dynamic PAT using global IP range vs. global interface vs. global IP Hoffa Cisco 0 10-25-2006 01:04 PM
XSL Question tp xsl:for-each and xsl:variable schaf@2wire.ch XML 1 05-27-2005 09:25 PM
Global variables on par with ASP's global.asa Wayne ASP .Net 2 11-11-2003 10:58 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57