RE: [xsl] Retaining value of a Global variable

Subject: RE: [xsl] Retaining value of a Global variable
From: Wendell Piez <wapiez@xxxxxxxxxxxxxxxx>
Date: Sat, 17 Jul 2004 15:11:12 -0400
Hi Vivek,

At 02:20 AM 7/17/2004, you wrote:
Hi Folks,
Thanks a lot for all your responses. Michael Kay has provided an alternative of using position() function. What I am trying to do is display the category heading only once if the article of that category is found.

Often the way this kind of problem is solved in XSLT is by rethinking: instead of "has an article of this category already been processed", think "is this the first article of its category; if so, X, if not, Y". That is, rather than conceptualizing the program's control flow, we leave that up to the processor, and merely consider the nodes' organization and how that maps to the result we want. Rather than thinking through a procedure, that is, we simply establish a specification of what output we want for a given input. So for example if a node is first (not temporally but within the static scope of document order), we do one thing, otherwise something else.

One consequence of this way of working is that a processor can proceed however it wants, as long as it gives us the specified output. It's like ordering in a restaurant -- we send word back to the kitchen that we want bowtie pasta with truffles (I should be so lucky), and let the chef decide how to prepare it.

Because yours appears to be a containment test (do any preceding nodes of a certain kind contain a certain string) rather than a simple value test, the solution is not quite as trivial as it often is; but M. David's second solution (that builds a string for checking, and then checks it) shows how it can be done notwithstanding. Note his setting of that variable

<xsl:variable name="checkString">
<xsl:for-each select="preceding-sibling::article/metadata/article-classification">
<xsl:value-of select="."/>

could be optimized slightly as

<xsl:variable name="checkString">
<xsl:copy-of select="preceding-sibling::article/metadata/article-classification"/>

and it would work as well. This is a case where it's important that it's *not* the same as

<xsl:variable name="checkString" select="preceding-sibling::article/metadata/article-classification"/>

because we deliberately need all the preceding sibling article's classifications to be gathered in a single string we can test (which happens if they are copied into a result tree, as opposed to the nodes themselves being bound to the variable). If it were a simple equality test, not a string-containment test, we could use that XPath by itself in our test (is the current node equal to any of those nodes?), and never need the variable at all.


"Thus I make my own use of the telegraph, without consulting
the directors, like the sparrows, which I perceive use it
extensively for a perch." -- Thoreau

Current Thread