xsl-list
[Top] [All Lists]

Re: Retaining value of a Global variable

2004-07-19 07:32:16
After being "woken up" to a fresh breath of "oh my goodness did I really swing and miss before the ball even crossed the plate" I am now ready to take on my day :) Thanks David for keeping me honest on this one... Howard Schultz is unfortunately going to have to reevaluate his profit loss statement for the day as the 5 dollars I had planned to contribute to the other Seattle monopoly for a dose of The Emerald Cities finest rise and shine elixir (naturally occuring caffeine being a fantastic substitute for the part normally played by the Sun) is being stapled to 5 more just like them and dropped off at my local Barnes and Noble in exchange for a copy of "the complete idiots guide to XSLT" (do they make one of those?) as it appears it would probably be in my best interest... ;)

For those of you keeping score at home David is more than correct in his suggestion to use keys to select both the first instance of an occurence within an XML document as well as all subsequent occurencess following in document order... And as he mentioned Jeni's site shows several great examples of using the Muenchian method for selecting and grouping in such a manner...

One thing to make a note of when you are using the contains() function (as was the case in this post) however is that the function itself is only going to compare the value of the first occurence of an element even if it is passed a set of nodes instead of just one. This is one of those gotchas that can sometimes nab you if youre not paying attention and relying on the result of something like...

<xsl:if test="contains(preceding-sibling::foo, 'bar')>do something</xsl:if>

to evaluate each preceding foo sibling and return true or false accordingly. It doesnt... it only will evaluate the value of the first matching element and return true or false based on a test of that node and that node only. Given the fact

<xsl:if test="preceding-sibling::foo = 'bar'">do something else</xsl:if>

will evaluate each preceding foo sibling and return true if any of the foo elements value is = 'bar' it's easy to see why this could catch even the most seasoned XSLT professional from time to time.

Although this may seem rediculous at first glance (form a human logic standpoint in many ways they seem almost interchangeable beyond the fact that one method tests for an occurence and the other tests for equality) a quick glance at the String Functions section of the XPath specification reveals exactly why this is... http://www.w3.org/TR/xpath#function-string

The first list item in this sections states very plainly: "A node-set is converted to a string by returning the string-value of the node in the node-set that is first in document order. If the node-set is empty, an empty string is returned."

If you scroll down just a bit you will find a definition for all of the string related functions of XPath. Function: boolean contains(string, string) is defined as such...

"The contains function returns true if the first argument string contains the second argument string, and otherwise returns false."

Given that less than a page before this we were told that a node-set is converted to a string by returning the string-value of the first node in document order we can now see why the contains function limits the XPath statement preceding-sibling::foo to only the first occurence... It doesnt look at the XPath statement in the same way the XSLT processor looks at it... it simply realizes that to complete its task of looking for an instance of a string inside another string it first needs to make an attempt at casting any non-string types to a string type and then make the comparison. When the function receives the return value from the cast it makes its comparison, returns true or false based on its findings, and then kicks back until such time as a string comparison between two strings is needed again.

Anyway, I didnt mean to try an take away from David's original point that this problem could be solved by using keys to group common elements. But I have been caught by the contains() function gothcha enough times to want to make sure that this portion of the posted problem was explained in a way as to allow the proper usage of keys for grouping when using the contains() function to search for an occurence instead of doing direct string comparisons as is the normal case when implementing any sort of grouping solution using the Meunchian method.

Thanks again for catching this David! :)

Best regards,

<M:D/>

----- Original Message ----- From: "David Carlisle" <davidc(_at_)nag(_dot_)co(_dot_)uk>
To: <xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com>
Sent: Monday, July 19, 2004 3:18 AM
Subject: Re: [xsl] Retaining value of a Global variable




Solution 2 - The second solution requires utilization of the preceding-sibling axis in XPath. The problem with using preceding-sibling in any sort of test is as the processor continues through the tree another preceding-sibling is added to the list of preceding-siblings. This test will evaluate each and every preceding-sibling so it doesnt take long for performance to become a BIG issue.


this is essentially why "muenchiam grouping" using keys is a big win.
The original posters (rephrased) problem sounds like the canonical use
case for the grouping techniques (as explaied at
www.jenitennison.com/xslt/grouping)

David

________________________________________________________________________
This e-mail has been scanned for all viruses by Star Internet. The
service is powered by MessageLabs. For more information on a proactive
anti-virus service working around the clock, around the globe, visit:
http://www.star.net.uk
________________________________________________________________________

--+------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--+--