RE: [xsl] Traversing nodes and storing a matched value

Subject: RE: [xsl] Traversing nodes and storing a matched value
From: "Michael Kay" <mike@xxxxxxxxxxxx>
Date: Wed, 29 Jun 2005 19:52:24 +0100
XSLT 1.0 doesn't allow variables to be used in a match pattern.

Michael Kay
http://www.saxonica.com/
 

> -----Original Message-----
> From: Mat Bergman [mailto:matbergman@xxxxxxxxx] 
> Sent: 29 June 2005 19:35
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Subject: RE: [xsl] Traversing nodes and storing a matched value
> 
> This looks like a most elegant solution. One
> head-scratching error occurs when I play with it using
> the MSXML processor:
> Variables may not be used within this expression.
> menu[not(existes = -->$siteID<--)]
> 
> When I hard-code the value in place of the variable,
> it works fine. Am I missing something?
> 
> Thanks,
> 
> -Mat
> 
> --- Aron Bock <aronbock@xxxxxxxxxxx> wrote:
> 
> > Mat,
> > 
> > You may want to change your calling sequence -- by
> > the time you 
> > "parseExclusions" you've already written an "ul". 
> > Anyway, to answer your 
> > question, XSL is set oriented, so you could
> > something like this to write 
> > only those menus containing at least 1 <existes>  =
> > siteID:
> > 
> > This input:
> > 
> > <data>
> >     <menu id="1"><existes>01</existes></menu>
> >     <menu
> >
> id="2"><existes>1</existes><existes>2</existes></menu>
> >     <menu id="3"><existes>2</existes></menu>
> > </data>
> > 
> > Against this XSL:
> > 
> > <?xml version="1.0" encoding="iso8859-1"?>
> > <xsl:stylesheet version="1.0" 
> > xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
> >     <xsl:output method="xml" indent="yes"/>
> >     <xsl:strip-space elements="*"/>
> > 
> >     <xsl:variable name="siteID" select="2"/>
> > 
> >     <xsl:template match="node()|@*">
> >         <xsl:copy><xsl:apply-templates
> > select="node()|@*"/></xsl:copy>
> >     </xsl:template>
> > 
> >     <xsl:template match="menu[not(existes =
> > $siteID)]"/>
> > 
> > </xsl:stylesheet>
> > 
> > produces:
> > 
> > <?xml version="1.0" encoding="UTF-8"?>
> > <data>
> >   <menu id="2">
> >     <existes>1</existes>
> >     <existes>2</existes>
> >   </menu>
> >   <menu id="3">
> >     <existes>2</existes>
> >   </menu>
> > </data>
> > 
> > Thus, when you call write-menu, you may want to pass
> > in only those menus 
> > with contain a qualifying existes.
> > 
> > --A
> > 
> > 
> > >From: Mat Bergman <matbergman@xxxxxxxxx>
> > >Reply-To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> > >To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> > >Subject: [xsl] Traversing nodes and storing a
> > matched value
> > >Date: Tue, 28 Jun 2005 20:52:17 -0700 (PDT)
> > >
> > >My efforts to streamline my stylesheet into
> > something
> > >well-formed are paying off with help from this
> > list. I
> > >am currently working with XML input that looks like
> > >this:
> > >
> > ><menudata>
> > >	<menu name="link1">
> > >	<exsites>0</exsites>
> > >	</menu>
> > >	<menu name="link2">
> > >	<exsites>0</exsites>
> > >		<menu name="link2a">
> > >		<exsites>1</exsites>
> > >		<exsites>2</exsites>
> > >		</menu>
> > >	</menu>
> > ></menudata>
> > >
> > >The value of the <exsites> element determines if
> > its
> > >parent <menu> element will appear in the output,
> > based
> > >on a $siteID parameter set in the stylesheet. In
> > some
> > >cases, <menu> has multiple <exsites> children.
> > >
> > >I'm not clear how to use XSL to say, "if the value
> > of
> > >ANY <exsite> matches $siteID, then flag its
> > parent's
> > >node for different processing". Here's my attempt
> > (the
> > >section where I'm in trouble is commented):
> > >
> > ><?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:strip-space elements="*"/>
> > >
> > ><!-- siteID determines if a link is displayed for a
> > >specific cobrand -->
> > ><xsl:param name="siteID" select="2"/>
> > >
> > ><xsl:template match="/menudata">
> > >	<xsl:call-template name="write-menu">
> > >		<xsl:with-param name="items" select="menu"/>
> > >	</xsl:call-template>
> > ></xsl:template>
> > >
> > ><xsl:template name="write-menu">
> > >	<xsl:param name="items" select="/.."/>
> > >
> > >	<ul>
> > >		<xsl:for-each select="$items">
> > >			<xsl:call-template name="parseExclusions"/>
> > >		</xsl:for-each>
> > >	</ul>
> > >
> > ></xsl:template>
> > >
> > ><xsl:template name="parseExclusions">
> > >
> > ><!-- Check <exsites> for a match against $siteID -
> > if
> > >a match, don't display -->
> > >	<xsl:for-each select="exsites">
> > >		<xsl:if test="current()=$siteID">
> > >
> > ><!-- This is where I need the stylesheet not to
> > write
> > >the link if any of the <exsites> values match the
> > >$siteID parameter -->
> > ><!-- For now I'm just writing out the value if it
> > >matches $siteID -->
> > >		<xsl:value-of select="current()"/>
> > >		</xsl:if>
> > >	</xsl:for-each>
> > >
> > >		<li>
> > >			<xsl:value-of select="@name"/>
> > >			<xsl:if test="menu">
> > >				<xsl:call-template name="write-menu">
> > >					<xsl:with-param 
> name="items" select="menu"/>
> > >				</xsl:call-template>
> > >			</xsl:if>
> > >		</li>
> > >
> > ></xsl:template>
> > >
> > ></xsl:stylesheet>
> > >
> > >
> > >My instinct is to set a boolean variable if any
> > ><exsite> element matches, then use that variable to
> > >control the output. Something like this (in
> > >pseudo-code):
> > >
> > ><xsl:for-each select="exsites">
> > >	<xsl:if test="current()=$siteID">
> > >	<!-- set variable - var excludeFlag = 1 -->
> > >	</xsl:if>
> > ></xsl:for-each>
> > >
> > ><!-- write tag - if (excludeFlag!=1). -->
> > ><li>
> > ><xsl:value-of select="@name"/>
> > >.
> > ></li>
> > ><!-- /if -->
> > 
> >
> _________________________________________________________________
> > Is your PC infected? Get a FREE online computer
> > virus scan from McAfeeR 
> > Security.
> >
> http://clinic.mcafee.com/clinic/ibuy/campaign.asp?cid=3963
> > 
> > 
> 
> 
> 
> 		
> ____________________________________________________ 
> Yahoo! Sports 
> Rekindle the Rivalries. Sign up for Fantasy Football 
> http://football.fantasysports.yahoo.com

Current Thread