Subject: RE: [xsl] Can't identify last ancestor node From: "Michael Kay" <mike@xxxxxxxxxxxx> Date: Tue, 28 Jun 2005 10:01:19 +0100 |
You haven't told us what the context node is for your code snippets - presumably it's the <menu> element that you're testing? In that case they don't make any sense at all. Looking at the ancestors of a node can't tell you whether it has any following siblings, for example. (From your question, I think you may have confused your ancestors with your descendants). Best way to do this is probably to set a global variable to the last menu element: <xsl:variable name="last-menu" select="(//menu)[last()]"/> and then when processing each menu element, test <xsl:if test=". is $last-menu"> (XSLT 2.0) <xsl:if test="generate-id(.) = generate-id($last-menu)"/> (XSLT 1.0) Michael Kay http://www.saxonica.com/ > -----Original Message----- > From: Mat Bergman [mailto:matbergman@xxxxxxxxx] > Sent: 28 June 2005 09:36 > To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx > Subject: [xsl] Can't identify last ancestor node > > 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 -> |
---|---|---|
[xsl] Can't identify last ancestor , Mat Bergman | Thread | Re: [xsl] Can't identify last ances, Sam D. Chuparkoff |
RE: [xsl] XSL siblings, Michael Kay | Date | Re: [xsl] XSL siblings, -= jay =- |
Month |