Re: Re: [xsl] How to do an 'existence' test in XSL? - Simple but Generalised

Subject: Re: Re: [xsl] How to do an 'existence' test in XSL? - Simple but Generalised
From: Wendell Piez <wapiez@xxxxxxxxxxxxxxxx>
Date: Thu, 23 Dec 2004 14:42:13 -0500
Hi Ben,

At 07:28 AM 12/23/2004, you wrote:
I wondered if Mukul's suggestion could be generalised to function on cases where the desired tags in the input xsl may be at any level of nesting e.g. with 'alertBox' we might have :

 <root>
   <othertag>
     <gui type="alertBox"></gui>
   </othertag>
   <gui type="tooltip"></gui>
   <gui type="help"></gui>
   <gui type="tooltip"></gui>
   <othertag>
     <deepertag>
       <gui type="alertBox"></gui>
     </deepertag>
   </othertag>
   <gui type="tooltip"></gui>
   <gui type="help"></gui>
 </root>

By changing the gui select in the for-each and the if test from preceeding-sibling to preceeding it (I think) simply scans backwards in the document to see if it has already encountered the type or not.

 <?xml version="1.0" encoding="UTF-8"?>
 <xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>

<xsl:output method="xml" indent="yes" />

 <xsl:template match="/root">
   <root>
     <xsl:for-each select="//gui">
       <xsl:if test="not(@type =
 preceding::gui/@type)">
         <xsl:element name="{@type}" />
       </xsl:if>
     </xsl:for-each>
   </root>
 </xsl:template>

</xsl:stylesheet>

I have not tested it exhaustively, but it seems to work perfectly, and does not depend on knowing what types are available beforehand.

It certainly works, and has been used. In fact it might be called the "canonical" solution. (As Mukul remarked, sometimes it also needs to be extended a bit to account for ancestors.)


+In what ways might this +not+ be the general solution to the problem?+

It's very general, but commonly avoided simply because of its performance implications. (The simple shift from preceding:: to preceding-sibling::, in cases where the nodes are not scattered, helps with this which may be why Mukul used the latter.) In a naive implementation, the entire tree will be traversed backwards to the beginning for every @type attribute checked. That's pretty serious cycling.


It is certainly logical, and elegant.

Yes, as XSLT so often is, when you give it a chance. Though admittedly its logic is its own. :-)


You also wrote:
However, the scenario I outlined was overly simplistic.

+It should not be assumed that the gui tags are are siblings. They may be scattered throughout the document at various nestings+

One of my additional problems is that I am using PHP5 and thus James Clark's expat parser, which doesn't support keys?

Expat is a XML parser, not an XSLT processor. I don't know offhand which processor PHP5 is using. But determining whether keys are supported is easy. (Clark's XT processor didn't implement keys but that's a different chunk of code from expat. For one, XT is in Java while Expat is in C.)


In this case I wonder which of the various proposed techniques will work!

Both my in-between solution, and Dimitre's (which I'll let him explain, but which amounts to a more sophisticated XSLT-2 version of the approach I used, using a sequence instead of a node-set) will both work with scattered nodes, given a tweak or two. So will George's brute-force technique.


Cheers,
Wendell


====================================================================== Wendell Piez mailto:wapiez@xxxxxxxxxxxxxxxx Mulberry Technologies, Inc. http://www.mulberrytech.com 17 West Jefferson Street Direct Phone: 301/315-9635 Suite 207 Phone: 301/315-9631 Rockville, MD 20850 Fax: 301/315-8285 ---------------------------------------------------------------------- Mulberry Technologies: A Consultancy Specializing in SGML and XML ======================================================================

Current Thread