Subject: Re: [xsl] Get Position of Node in Ancestor Context From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx> Date: Mon, 10 Mar 2003 17:33:58 +0000 |
Hi Ted, > Answered my own question, but would still be interested in knowing > what others think of this solution... > > <xsl:template match="input|select|textarea"> > <xsl:copy> > <xsl:for-each select="@*"> > <xsl:copy /> > </xsl:for-each> > <xsl:variable name="currElemId" select="@id" /> > <xsl:attribute name="tabindex"></xsl:attribute> > <xsl:for-each > select="ancestor::form//select|ancestor::form//input|ancestor::form// > textarea"> > <xsl:if test="not(@type = 'hidden') or @type = 'submit'"> > <xsl:if test="@id = $currElemId"> > <xsl:attribute name="tabindex"><xsl:value-of > select="position()" /></xsl:attribute> > </xsl:if> > </xsl:if> > </xsl:for-each> > <xsl:apply-templates /> > </xsl:copy> > </xsl:template> I think that you'd probably be better off using <xsl:number> here. Try: <xsl:template match="input | select | textarea"> ... <xsl:attribute name="tabindex"> <xsl:number from="form" level="any" count="*[self::input or self::select or self::textarea] [@type != 'hidden']" /> </xsl:attribute> ... </xsl:template> You could use "input[@type != 'hidden'] | select[@type != 'hidden'] | textarea[@type != 'hidden']" as the value of the count attribute if you prefer. Note that I dropped the "or @type = 'select'" since any element with a type attribute equal to 'select' will pass the "@type != 'hidden'" test. > The style sheet basically adds tabindex attributes to all form > elements. What I'm unhappy with is the value of the select attribute > of the second for-each element (the one that creates a node set of > all child elements of a FORM element, regardless of what separates > them). It seems odd that I have to fully qualify the child element > I'm looking for, but using ancestor::form//select|input|textarea > only matches the first element in the list. Yes; in XPath 2.0, we'll be able to use: ancestor::form//(select | input | textarea) which is a good deal shorter, and likewise with the count attribute above, we'll be able to do: (input | select | textarea)[@type != 'hidden'] > Also, what is the performance impact on setting up such for-each > loops and is there a faster way to reproduce this node-set in the > context of the current element (call-template with-param???)? Numbering based on position within the node tree is always fairly expensive because it can require a lot of node visits. If the <input>, <select> and <textarea> elements are siblings, you can use level="single", which will mean that the processor doesn't have to look at quite as many nodes. Or you could use a step-by-step recursive template and pass the current count on from sibling to sibling. But unless you find performance is really suffering here, I'd stick with the <xsl:number> solution above. By the way, rather than: <xsl:for-each select="@*"><xsl:copy /></xsl:for-each> you could just do: <xsl:copy-of select="@*" /> Cheers, Jeni --- Jeni Tennison http://www.jenitennison.com/ XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] Get Position of Node in A, Ted Stresen-Reuter | Thread | RE: [xsl] Get Position of Node in A, Michael Kay |
Re: [xsl] trying to create a node-s, Robert P. J. Day | Date | RE: [xsl] Xpath patern question, Hélder Sousa |
Month |