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: Mukul Gandhi <mukul_gandhi@xxxxxxxxx>
Date: Thu, 23 Dec 2004 05:59:35 -0800 (PST)
The modified solution you wrote would cause problem,
if <gui type=""> nodes would exist in the ancestor
axis.. (because preceding axis does'nt include nodes
from the ancestor axis).

for e.g., if your XSL is applied to this XML -
<?xml version="1.0" encoding="UTF-8"?>
<root>
   <othertag>
     <gui type="x"></gui>
   </othertag>
   <gui type="tooltip"></gui>
   <gui type="help"></gui>
   <gui type="tooltip"></gui>
   <othertag>
     <gui type="alertBox"> <!-- Please note here -->
       <gui type="alertBox"></gui>
     </gui> 
   </othertag>
   <gui type="tooltip"></gui>
   <gui type="help"></gui>
</root>

it will produce output -
<root>
   <x/>
   <tooltip/>
   <help/>
   <alertBox/>
   <alertBox/>
</root>

We need to write the XSL like this -
<?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)
or (@type = ancestor::gui/@type))">
        <xsl:element name="{@type}" />
      </xsl:if>        
    </xsl:for-each>
  </root>
</xsl:template>
  
</xsl:stylesheet>

Regards,
Mukul

--- ben@xxxxxxxxxxxxx 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. 
> 
> +In what ways might this +not+ be the general
> solution to the problem?+ 
> 
> It is certainly logical, and elegant.
> 
> I look forward to your responses with interest.
> 
> Dr T.B.Senior
> 
> 
> You wrote:
> > Here is a simple approach you can try..
> > 
> > <?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-sibling::gui/@type)">
> >         <xsl:element name="{@type}" />
> >       </xsl:if>
> >     </xsl:for-each>
> >   </root>
> > </xsl:template>
> >   
> > </xsl:stylesheet>
> > 
> > When the above XSL is applied to XML -
> > <?xml version="1.0" encoding="UTF-8"?>
> > <root>
> >   <gui type="alertBox"></gui>
> >   <gui type="tooltip"></gui>
> >   <gui type="help"></gui>
> >   <gui type="tooltip"></gui>
> >   <gui type="alertBox"></gui>
> >   <gui type="tooltip"></gui>
> >   <gui type="help"></gui>
> > </root>  
> > 
> > The o/p recieved is -
> > <?xml version="1.0" encoding="UTF-8"?>
> > <root>
> >   <alertBox/>
> >   <tooltip/>
> >   <help/>
> > </root>
> > 
> > Regards,
> > Mukul
> > 
> > --- ben@xxxxxxxxxxxxx wrote:
> > 
> > > I'm having great difficulty understanding how/if
> XSL
> > > provides the tool to satisfy the following
> simple
> > > requirement. 
> > > 
> > > Lets say I have some simple xml like :
> > > 
> > > <gui type="alertBox">...</gui>
> > > <gui type="tooltip">...</gui>
> > > <gui type="help">...</gui>
> > > <gui type="tooltip">...</gui>
> > > <gui type="alertBox">...</gui>
> > > <gui type="tooltip">...</gui>
> > > <gui type="help">...</gui>
> > > 
> > > To simplify things... imagine transforming this
> > > document in such a way that we have something
> like :
> > > 
> > > <alertBox/>
> > > <tooltip/>
> > > <help/>
> > > 
> > > i.e. I would like the XSL to result in one
> output
> > > per gui type.
> > > 
> > > So there is the problem... how on earth do I
> process
> > > the xml such that it results in an output per
> +type+
> > > rather than for each instance (is that explained
> > > well enough?)... i.e. it's easy to match on the
> > > attributes but each match produces output so I
> would
> > > get :
> > > 
> > > <alertBox/><alertBox/>
> > > <tooltip/><tooltip/><tooltip/>
> > > <help/><help/>
> > > 
> > > Can anyone offer advice on the way in which I
> ought
> > > to approach this problem?
> > > 
> > > Kindest regards,
> > > 
> > > Ben



		
__________________________________ 
Do you Yahoo!? 
Yahoo! Mail - Helps protect you from nasty viruses. 
http://promotions.yahoo.com/new_mail

Current Thread