Subject: [xsl] Can't identify last ancestor node From: Mat Bergman <matbergman@xxxxxxxxx> Date: Tue, 28 Jun 2005 01:36:09 -0700 (PDT) |
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="' 	
'" /> <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"><li></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"> <ul> </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"></li></ul> </xsl:text> </xsl:when> <!-- If it's not the last sub-menu, close with an </li> --> <xsl:otherwise> <xsl:text disable-output-escaping="yes"></li> </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 |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] XSL siblings, omprakash . v | Thread | RE: [xsl] Can't identify last ances, Michael Kay |
RE: [xsl] test if null, Michael Kay | Date | Re: [xsl] Linking to a 6 level tag , Kahlil Johnson |
Month |