This is the mail archive of the xsl-list@mulberrytech.com mailing list .


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

RE: where to put the filter?


>
>So given a source document like this:
>
>   <rootelem title="MyRoot">
>     <childelem>child1</childelem>
>     <childelem>child2<grandchildelem>grandkid</grandchildelem></childelem>
>   </rootelem>
>
>you might have a template rule like this:
>
>   <xsl:template match="/rootelem">
>     <newrootelem>
>       <xsl:value-of select="@title"/>
>       <xsl:apply-templates />
>     </newrootelem>
>   </xsl:template>
>
>See? xsl:template contains both xsl:value-of and xsl:apply-templates. The
>result tree will contain:
>
>   <newrootelem>
>     MyRoot
>     child1 child2 grandkid
>   </newrootelem>
>
>[Now comes the part where Evan jumps in and qualifies all the above. :)]


I wouldn't have if it wasn't for your open, welcoming challenge :)

For that matter, now that I've gone through this exercise, here's the
overkill version; treat it like a tutorial.

If you're talking about built-in template rules for text, you might as well
get the whitespace right:

<newrootelem>MyRoot
     child1
     child2grandkid
   </newrootelem>


How this result came about, step-by-step:

<xsl:value-of select="@title"/> inserted "MyRoot" in the result tree as the
immediate child of <newrootelem>, without any intervening whitespace,
because whitespace in the stylesheet is thrown out, unless it is adjacent to
any non-whitespace text.

Without an explicit select attribute, <xsl:apply-templates/> always selects
children of the context node (elements, text, comments, and processing
instructions).  In the above example, it selects the following nodes in this
order:

1. (text) line break + spaces after <rootelem>'s open tag
2. (element) first <childelem>
3. (text) line break + spaces after first <childelem>
4. (element) second <childelem>
5. (text) line break + spaces after second <childelem>


Since there are no explicit template rules to match any of the above nodes,
the built-in rules are used as follows:

1. copy text to result
2. apply templates to children
3. copy text to result
4. apply templates to children
5. copy text to result


The implicit call to <xsl:apply-templates/> in #2 above selects the
following nodes in this order:

a. (text) child1


Built-in rule is used as follows:

a. copy text to result


The implicit call to <xsl:apply-templates/> in #4 above selects the
following nodes in this order:

a. (text) child2
b. (element) <grandchildelem>


Built-in rules are used as follows:

a. copy text to result
b. apply templates to children


The implicit call to <xsl:apply-templates/> in b. above selects the
following nodes in this order:

1. (text) grandkid


Built-in rule is used as follows:

1. copy text to result


Being aware of the nodes selected by <xsl:apply-templates/> as well as the
template rules matching them, whether built-in or provided explicitly in the
stylesheet, will enable you to better understand why the results of your
transformations look the way they do, as well as to have better control over
the result when controlling whitespace is important.

To summarize, here are the built-in template rules for each of the seven
XPath node types:

Elements:     Apply templates to children
Text:         Copy text to the result tree
Comments:     Do nothing
PIs:          Do nothing
Attributes:   Copy the value of the attribute to the result tree
Namespace:    Do nothing
Root:         Apply templates to children


Note that unless you selectively process nodes using the select attribute of
<xsl:apply-templates/>, the only nodes you'll have to worry about are those
that qualify as children (the first four in the above list).  Since the
built-in rules for comments and PIs are to do nothing, all you really have
to worry about is being aware of how built-in rules will be applied to
elements and text, which we covered in painful detail above.

To avoid processing whitespace nodes in the source tree, you can use
<xsl:strip-space/> in your stylesheet, the details of which I won't go into
here.

The section on whitespace in chapter 3 of Michael Kay's book (XSLT
Programmer's Reference) was very helpful to me and I highly recommend it
along with the rest of the book.

John, are you happy now?  Don't worry, I'm done for now.

Evan Lenz
elenz@xyzfind.com
http://www.xyzfind.com
XYZFind, the search engine *designed* for XML
Download our free beta software: http://www.xyzfind.com/beta


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]