Subject: Re: [xsl] returning nodes which have a specific child From: Michael Ludwig <mlu@xxxxxxxxxxxxx> Date: Thu, 02 Jul 2009 10:53:44 +0200 |
Thanks very much for that! Worked a treat.
I'm relatively new to xsl and to be honest a lot of it seems like a black art. Can you briefly describe what your solution does?
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="@*|node()"><!-- identity template --> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template>
The most important thing to understand is IMHO the so-called identity template (also "copy template"), of which you see the canonical form above. This copies the input unaltered. (The input is not the literal XML, but the input tree, that is what the XSL processor makes of what the XML parser produces - see XDM, XPath Data Model.)
I have an editor macro that produces the stylesheet skeleton plus identity template, as this is almost always the right starting point for a new stylesheet.
Note that XSLT has built-in template rules that basically lose the markup and display the text only. Most of the time you'll want to supplant these by the identity template. Some people even think that the identity template should have been the built-in template rule.
<xsl:template match="*" priority="-0.4" ><!-- skip unwanted --> <xsl:apply-templates select="*"/> </xsl:template>
Copying input to output is fine, but most of the time you want to make some changes. So you insert other templates (rules) that take priority over the identity template.
Priority is expressed as a decimal number. It is implicit from the match pattern. In the above case, the match pattern has the same priority (-0.5) as that of the identity template. So I give it an explicit priority of -0.4 so that it takes precedence over the identity template for matching nodes.
This template matches element nodes (*). So does the identity template (by virtue of node(), which is a node test), but this one takes precedence due to a higher priority.
It doesn't do much. You want to lose these nodes, but process their child elements, so you don't copy anything and <apply-templates> to the child elements, which are selected as "*". If I didn't process child elements, well, processing would stop at this point in the input tree, which is not what I want. I want processing to go all the way downtree.
<xsl:template match="*[*[@name='CONTENT']]" ><!-- keep wanted --> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template>
</xsl:stylesheet>
This last template is for the nodes you want to keep. The template content should look familiar. Yes, that's the identity template implementation again. You copy the element node and then process all attributes (@*) and children (node()). They'll be picked up by either the identity template, in which case their copied, or the skip template, in which case their skipped.
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] returning nodes which hav, jim mcgovern | Thread | Re: [xsl] returning nodes which hav, Wendell Piez |
Re: [xsl] returning nodes which hav, jim mcgovern | Date | RE: [xsl] returning nodes which hav, Michael Kay |
Month |