Subject: Re: [xsl] How to avoid applying templates several times to the same descendant From: Jeni Tennison <mail@xxxxxxxxxxxxxxxx> Date: Tue, 8 May 2001 09:05:46 +0100 |
Hi Joakim, > My problem is: How can I select to "execute" only selected nodes, > when I don't know what level they are at, or what names they have. > In addition to the "spec" above, there are a bunch of other > templates that also have to apply to the elements in question. I think that the answer is 'use modes'. Moded templates allow you to apply several different templates to the same nodes in different circumstances. I'll show you the solution to the problem that you gave (thanks for providing, input, output and some XSLT, btw - very helpful) which will hopefully demonstrate how to use them in this problem. The general approach is to apply templates to the top-level ATLAS element multiple times - once for each of the unique @ATTR values, each time making a copy of the ATLAS element and its relevant children. Because I also want to apply templates to the ATLAS element as a controlling template, I use the 'copy' mode to distinguish between the normal processing flow and the special 'copying' process. I use a parameter to pass in the @ATTR value that I'm currently making a copy for. I've used the same key as you: <xsl:key name="UniqueATTR" match="*[@ATTR]" use="@ATTR"/> The top-level template has to control the process, applying templates to the document ATLAS element for each of the unique @ATTR values. I loop over the unique values, just as you did, but apply templates to the ATLAS element in copy mode and pass the @ATTR value as a parameter. <xsl:template match="ATLAS"> <xsl:variable name="atlas" select="." /> <xsl:for-each select="//*[@ATTR] [generate-id() = generate-id(key('UniqueATTR', @ATTR)[1])]"> <xsl:apply-templates select="$atlas" mode="copy"> <xsl:with-param name="attr" select="@ATTR" /> </xsl:apply-templates> </xsl:for-each> </xsl:template> The next template is applied as a result. It matches the ATLAS element in copy mode and accepts the $attr parameter. It creates a ATLAS element with the relevant @ATTR value (using literal result elements rather than xsl:element/xsl:attribute to make things clearer). Then it applies templates to *its* children, again in 'copy' mode and still passing the $attr parameter through. <xsl:template match="ATLAS" mode="copy"> <xsl:param name="attr" /> <ATLAS ATTR="{$attr}"> <xsl:apply-templates mode="copy"> <xsl:with-param name="attr" select="$attr" /> </xsl:apply-templates> </ATLAS> </xsl:template> The final template is applied on these child elements. Again it's in copy mode with an $attr parameter. Within, I test whether the element I'm looking at either hasn't got an @ATTR attribute or has one with a value equal to the $attr parameter. In either of those cases, I make a copy of it and then move on recursively to the next layer in the hierarchy. <xsl:template match="*" mode="copy"> <xsl:param name="attr" /> <xsl:if test="not(@ATTR) or @ATTR = $attr"> <xsl:copy> <xsl:copy-of select="@*" /> <xsl:apply-templates mode="copy"> <xsl:with-param name="attr" select="$attr" /> </xsl:apply-templates> </xsl:copy> </xsl:if> </xsl:template> I hope that helps, 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] How to avoid applying tem, Jarno Elovirta | Thread | [xsl] XSL output media type, Theodore Weatherly |
Re: [xsl] parsing strings, Swen Thuemmler | Date | Re: [xsl] Can one <xsl:choose> <xsl, Jeni Tennison |
Month |