XML Editor
Sign up for a WebBoard account Sign Up Keyword Search Search More Options... Options
Chat Rooms Chat Help Help News News Log in to WebBoard Log in Not Logged in
Show tree view Topic
Topic Page 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 Go to previous topicPrev TopicGo to next topicNext Topic
Postnext
Eric RehmSubject: Global vs. Local xsl:variable Scope
Author: Eric Rehm
Date: 28 Oct 1999 11:55 AM
I'm confused on the scope and use of xsl:param and xsl:variable.
I've got the usual "collection":

(books)
(book)(title)Moby Dick(/title)...(/book)
(book)(title)Les Miserables((/title)...(/book)
...
(/books)

I want to craft a style sheet that will alter the color of (title) text between two values, say red and green. So, I have a global boolean parameter pflip and a global boolean variable flip. I use the style sheet below to "flip" between green and red. But, upon each "call" to the book template, "flip" is reinitialized to it's global value. So, all I get is green text, because flip is always "1".

How do I do initialize a variable ONCE outside it's local scope?

/eric

---------

(!-- flip.xsl --)

(xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform")
(xsl:template match="*|/")(xsl:apply-templates/)(/xsl:template)
(xsl:template match="text()|@*")(xsl:value-of select="."/)(/xsl:template)

(!-- Initialize flip variable --)
(xsl:param name="pflip" expr="1" /)
(xsl:variable name="flip" expr="{$pflip}"/)

(!-- Each book: alternate book title colors --)
(xsl:template match="book")
(xsl:choose)
(xsl:when test="boolean($flip)=true()")
(!-- Green title --)
(font color=#00ff00)(xsl:value-of select="title"/)(/font)
(!-- Flip --)
(xsl:variable name="flip" expr="0"/)
(/xsl:when)
(xsl:otherwise)
(!-- Red title --)
(font color=#ff0000)(xsl:value-of select="title"/)(/font)
(!-- Flip --)
(xsl:variable name="flip" expr="1"/)
(/xsl:otherwise)
(/xsl:choose)
(/xsl:template)

(xsl:template match="books")
(html)
(head)(title)Books of different colors(/title)(/head)
(body)(xsl:apply-templates/)(/body)
(/html)
(/xsl:template)

(/xsl:stylesheet)

Postnext
Omri TraubSubject: Global vs. Local xsl:variable Scope
Author: Omri Traub
Date: 28 Oct 1999 12:23 PM
Hi Eric,

One thing you should realize about xsl variables is that they are not variables in the sense you think they are. They can only be set once, at initialization time, and can not be changed thereafter. So the line: (xsl:variable name="flip" expr="0"/) in your local template does nothing but declare a local variable "flip", which shadows the global variable of the same name. You never use that variable, and when you return to the calling template the local binding goes away, and you are left with the global variable.

A note on param vs. variable. An xsl:param at the global level acts just like a global variable. The only difference is that you can set the value of that variable outside the stylesheet, through the eXcelon interfaces. This can be very useful for changing the behavior of the stylesheet based on how it is being called.

So, given that you want to alternate colors, I would do the following:

(ul)
(xsl:for-each select="/books/book")
(li)
(xsl:choose)
(xsl:when test="position() mod 2 = 0")
(font color="#ff0000")(xsl:value-of select="title"/)(/font)
(/xsl:when)
(xsl:otherwise)
(font color="#00ff00")(xsl:value-of select="title"/)(/font)
(/xsl:otherwise)
(/xsl:choose)
(/li)
(/xsl:for-each)
(/ul)

I select the set of books with xsl:for-each. I then choose the color based on the current book's position in the list of all books selected. I use the xsl "mod" operator to get the desired flipping effect.

Hope this helps,

- Omri

Postnext
Eric RehmSubject: Global vs. Local xsl:variable Scope
Author: Eric Rehm
Date: 28 Oct 1999 07:11 PM
Thanks. That works.

However, why do I get a position() that's multiplied by two (hence only green titles) when I do it using a template match instead of the (xsl:for-each)?

(!-- Each book: alternate book title colors --)
(xsl:template match="book")
(xsl:choose)
(xsl:when test="position() mod 2 =0")
(!-- Green title --)
(font color=#00ff00)
(xsl:value-of select="position()"/) (xsl:value-of select="title"/)(/font)
((/xsl:when)
(xsl:otherwise)
(!-- Red title --)
(font color=#ff0000)
(xsl:value-of select="position()"/) (xsl:value-of select="title"/)(/font)
((/xsl:otherwise)
(/xsl:choose)
(/xsl:template)

(xsl:template match="books")
(html)
(head)(title)Books of different colors /title)(/head)
(body)(xsl:apply-templates/)(/body)
(/html)
(/xsl:template)


Posttop
Omri TraubSubject: Global vs. Local xsl:variable Scope
Author: Omri Traub
Date: 29 Oct 1999 09:48 AM
Yes - you hit on a subtle issue in xsl.
position() is defined with respect to a "context node list". This is the list of nodes that the processor goes through. There are two ways to change this list. When you say: (xsl:apply-templates/) you are saying to the processor - please set the context node list to be the list of all children of the current node. When this new list is processed entirely, the processor continues on the old context node list. The same is true of (xsl:for-each select="...").

The problem you encountered is that (I am guessing without having seen your xml document) (xsl:apply-templates/) in the books template selects a mixtures of elements (book) and text nodes (white space or newlines between book elements). So when you ask for the position of a "book" element, you get the position with respect to the whole list of children of "books".
When you need to use position(), I recommend either for-each or apply-templates with a specific select expression.

On a different note - have you tried the xsl debugging features in stylus? If you hit F9 or select "Insert breakpoint" from the tools menu, you will be able to see a listing of all variables and values at the breakpoint. The other features is the processor trace which allows you to track the calling hierarchy of templates.

- Omri.

 
Topic Page 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 Go to previous topicPrev TopicGo to next topicNext Topic
Download A Free Trial of Stylus Studio 6 XML Professional Edition Today! Powered by Stylus Studio, the world's leading XML IDE for XML, XSLT, XQuery, XML Schema, DTD, XPath, WSDL, XHTML, SQL/XML, and XML Mapping!  
go

Log In Options

Site Map | Privacy Policy | Terms of Use | Trademarks
Stylus Scoop XML Newsletter:
W3C Member
Stylus Studio® and DataDirect XQuery ™are from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2016 All Rights Reserved.