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

Can't identify last ancestor node

Subject: Can't identify last ancestor node
From: Mat Bergman <matbergman@xxxxxxxxx>
Date: Tue, 28 Jun 2005 01:36:09 -0700 (PDT)
xsl if test ancestor
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?

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.