[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

Re: Can't identify last ancestor node

Subject: Re: Can't identify last ancestor node
From: "Sam D. Chuparkoff" <sdc@xxxxxxxxxx>
Date: Tue, 28 Jun 2005 05:48:16 -0700
with param disable output escaping
On Tue, 2005-06-28 at 01:36 -0700, Mat Bergman wrote:
> Using this XML data:
> 
> <menudata>
> 	<menu name="link1"/>
> 	<menu name="link2">
> 		<menu name="link2a"/>
> 		<menu name="link2b"/>
> 	</menu>
> </menudata>
> 
> 
> I am producing this HTML output:
> <ul>
> <li>link1</li>
> <li>link2
> 	<ul>
> 	<li>link2a</li>
> 	<li>link2b</li>
> 	</ul>
> </li>
> </ul>
> 
> I am using a convoluted stylesheet that tokenizes an
> attribute and generates the HTML output based on the
> attribute's value. My problem is identifying the last
> nested node, in this example "link2b", so that I can
> customize that node's output.
> 
> My complete stylesheet is below, but to summarize I
> made two attempts:
> 
> <xsl:for-each select="ancestor::menu">
> 	<xsl:if test="position()=last()">
> 	<xsl:text>Write custom end text here</xsl:text>
> 	</xsl:if>
> </xsl:for-each>
> 
> and
> 
> <xsl:if test="ancestor::menu[last()]">
> <xsl:text>Write custom end tag here</xsl:text>
> </xsl:if>
> 
> Both attempts wrote to each individual node, not just
> the last one. How can I tell my stylesheet to write
> one thing for the last <menu> node, and something else
> for the rest?

Don't use xsl:text to write xml. Don't think in terms of generating
start and end tags. You can't separate the two. Forget about the ul s
for a bit, pull out your conditions, and make certain your creation of
li s looks something like:

<li><xsl:value-of select="@name"/></li>

and nothing like:

<xsl:text
disable-output-escaping="yes">&lt;li&gt;</xsl:text>             
<xsl:value-of select="@name"/>
<xsl:text
disable-output-escaping="yes">&lt;/li&gt;</xsl:text>
 
Then you can start asking: How do I get some ul s in there? (Hint: no
xsl:text allowed. Really.)

Though someone else will have to answer because I'll be offline.

sdc

> Here's the entire stylesheet:
> 
> <?xml version="1.0"?>
> <xsl:stylesheet version="1.0"
>               
> xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
> 	
> <xsl:output method="html" indent="yes"/>
> 
> <!-- siteID determines if a link is displayed for a
> specific cobrand -->
> <xsl:param name="siteID" select="2"/>
> 
> <!-- Displays navigation -->
> <xsl:template match="/">
> 
> 	<ul>
> 
> 	<!-- tokenize all <menu> nodes -->
> 	<xsl:for-each select="//menu">
> 
> 		<!-- Tokenize attributes to check if siteID is
> excluded -->
> 		<xsl:call-template name="tokenize">
> 			<xsl:with-param name="string" select="@exsites"/>
> 			<xsl:with-param name="delimiters" select="','"/>
> 			<xsl:with-param name="level"
> select="'process-includeExclude'"/>
> 		</xsl:call-template>
> 
> 	</xsl:for-each>
> 
> 	</ul>
> 
> </xsl:template>
> 
> 
> <!-- Extract individual values from comma-delimited
> attribute -->
> <xsl:template name="tokenize">
> 	<xsl:param name="string" select="''" />
> 	<xsl:param name="delimiters" select="' &#x9;&#xA;'"
> />
> 	<xsl:param name="level" select="''" />
> 
> 	<xsl:call-template name="_tokenize-delimiters">
> 		<xsl:with-param name="string" select="$string" />
> 		<xsl:with-param name="delimiters"
> select="$delimiters" />
> 		<xsl:with-param name="level" select="$level" />
> 	</xsl:call-template>
> 
> </xsl:template>
> 
> 
> <xsl:template name="_tokenize-delimiters">
> 
> 	<xsl:param name="string" />
> 	<xsl:param name="delimiters" />
> 
> 	<xsl:param name="level" />
> 
> 	<xsl:param name="last-delimit"/> 
> 	<xsl:variable name="delimiter"
> select="substring($delimiters, 1, 1)" />
> 	
> 	<xsl:choose>
> 		<xsl:when test="not($delimiter)">
> 
> 		<!-- Sends individual attribute value for processing
> -->
> 		<xsl:call-template name="process-includeExclude" >
> 			<xsl:with-param name="currentExsite"><xsl:value-of
> select="$string"/></xsl:with-param>	
> 		</xsl:call-template>
> 
> 	   </xsl:when>
> 
> 	<!-- process string until all tokens are separated
> -->
>    <xsl:when test="contains($string, $delimiter)">
>      <xsl:if test="not(starts-with($string,
> $delimiter))">
>        <xsl:call-template name="_tokenize-delimiters">
>          <xsl:with-param name="string"
> select="substring-before($string, $delimiter)" />
>          <xsl:with-param name="delimiters"
> select="substring($delimiters, 2)" />
>        <xsl:with-param name="level" select="$level" />
> 
>        </xsl:call-template>
>      </xsl:if>
>      <xsl:call-template name="_tokenize-delimiters">
>        <xsl:with-param name="string"
> select="substring-after($string, $delimiter)" />
>        <xsl:with-param name="delimiters"
> select="$delimiters" />
>        <xsl:with-param name="level" select="$level" />
>      </xsl:call-template>
>    </xsl:when>
>    <xsl:otherwise>
>      <xsl:call-template name="_tokenize-delimiters">
>        <xsl:with-param name="string" select="$string"
> />
>        <xsl:with-param name="delimiters"
> select="substring($delimiters, 2)" />
>        <xsl:with-param name="level" select="$level" />
>      </xsl:call-template>
>    </xsl:otherwise>
>  </xsl:choose>
> </xsl:template>
> 
> 
> <xsl:template name="process-includeExclude"
> match="menu">
> <xsl:param name="currentExsite" select="''" />
> 
> 	<!-- check if siteID is excluded or included -->
> 	<xsl:if test="$currentExsite!=$siteID">
> 	<xsl:if test="@incsites=$siteID or @incsites=0">
> 
> 		<!-- Write <li> tags -->
> 		<xsl:text
> disable-output-escaping="yes">&lt;li&gt;</xsl:text>		
> 
> 		<!-- Write list content -->
> 		<xsl:value-of select="@name"/>
> 
> 		<!-- Nested list - Write nested <ul> tags -->
> 		<xsl:if test="count(menu) > 0">
> 		<xsl:text
> disable-output-escaping="yes">&#10;&lt;ul&gt;&#10;</xsl:text>
> 		</xsl:if>
> 
> 		<!-- Write </li> tags for top-level and nested items
> -->
> 		<xsl:if test="count(menu) = 0">
> 		
> 		<xsl:choose>
> 
> <!-- This is where I am having trouble.  I want this
> to appear only at the last menu/menu node. Instead
> it's selecting all menu ancestors. -->
> 
> 			<!-- If it's the last sub-menu, close with an </li>
> and a </ul> -->
> 			<xsl:when test="ancestor::menu[last()]">
> 				<xsl:text
> disable-output-escaping="yes">&lt;/li&gt;&lt;/ul&gt;
> 				</xsl:text>
> 			</xsl:when>
> 
> 			<!-- If it's not the last sub-menu, close with an
> </li> -->
> 			<xsl:otherwise>
> 				<xsl:text
> disable-output-escaping="yes">&lt;/li&gt;
> 				</xsl:text>			
> 			</xsl:otherwise>
> 
> 		</xsl:choose>
> 
> 		</xsl:if>
> 
> 	</xsl:if>	
> 	</xsl:if>		
> 
> 
> </xsl:template>
> 
> </xsl:stylesheet>
> 
> 
> Thanks,
> 
> -Mat
> 
> 
> 
> 
> __________________________________________________
> Do You Yahoo!?
> Tired of spam?  Yahoo! Mail has the best spam protection around 
> http://mail.yahoo.com 

Current Thread

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.