Wrox Programmer Forums
Go Back   Wrox Programmer Forums > XML > XSLT
|
XSLT General questions and answers about XSLT. For issues strictly specific to the book XSLT 1.1 Programmers Reference, please post to that forum instead.
Welcome to the p2p.wrox.com Forums.

You are currently viewing the XSLT section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
 
Old January 8th, 2007, 04:46 PM
Registered User
 
Join Date: Jan 2007
Posts: 3
Thanks: 0
Thanked 0 Times in 0 Posts
Default simple XSLT apply-templates question

Ok, so this should be a pretty quick "whether XSLT can do this or not", it seems like it really should be able to, but I can't find any examples of it:

I have a stylesheet that looks like this:

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:template match="foo">
<b> foo's bold text </b>
</xsl:template>

<xsl:template match="b">
<i> <xsl:value-of select="."/> </i>
</xsl:template>

</xsl:stylesheet>


My input is this:

<foo/>
<b> bold text outside of foo </b>

My output is this:
<?xml version="1.0"?>
<b> foo's bold text </b>
<i> bold text outside of foo </i>

My desired output is this:
<?xml version="1.0"?>
<i> foo's bold text </i>
<i> bold text outside of foo </i>


Essentially what I want is for my rule for <b> tags to be applied in the definition of my rule for <foo> tags. I know I could do a second pass, but that seems like a hack. Is this possible to do in one pass? It seems like there should be some random trick to do this since it seems like a common operation.

 
Old January 8th, 2007, 05:15 PM
Registered User
 
Join Date: Jan 2007
Posts: 3
Thanks: 0
Thanked 0 Times in 0 Posts
Default

just an FYI, I'm using libxml 20616, libxslt 10111 and libexslt 809 on a standard linux install


 
Old January 8th, 2007, 06:10 PM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

In XSLT 2.0 you write:

<xsl:template match="foo">
<xsl:variable name="temp">
  <b> foo's bold text </b>
</xsl:variable>
<xsl:apply-templates select="$temp/*"/>
</xsl:template>

Unfortunately XSLT 1.0 has a (crazy) restriction that you can't apply-templates to a "result tree fragment". Most processor have got around this by providing an extension function, xx:node-set() where the namespace assigned to prefix xx varies from processor to another. This allows you to write it as:

<xsl:template match="foo">
<xsl:variable name="temp">
  <b> foo's bold text </b>
</xsl:variable>
<xsl:apply-templates select="xx:node-set($temp/*)"/>
</xsl:template>


Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
 
Old January 9th, 2007, 01:50 PM
Registered User
 
Join Date: Jan 2007
Posts: 3
Thanks: 0
Thanked 0 Times in 0 Posts
Default

thanks Michael, that did the trick! took me a while to figure out that I had to add the exsl xmlns namespace for all this to work, but other than that, excellent and thorough response.

 
Old March 26th, 2007, 03:27 PM
Registered User
 
Join Date: Mar 2007
Posts: 2
Thanks: 0
Thanked 0 Times in 0 Posts
Send a message via AIM to korisu
Default

Quote:
quote:Originally posted by mhkay
Unfortunately XSLT 1.0 has a (crazy) restriction that you can't apply-templates to a "result tree fragment".
Does it really? What exactly are the restrictions on it?

The reason I ask is because I found a stylesheet yesterday that does precisely that. I made a small example to test it:


xml:
Code:
<parent>
    <child>
        <children>kid A</children>
        <children>kid B</children>
        <children>kid C</children>
        <children>kid D</children>
    </child>
    <child>
        <kid>brats</kid>
        <kid>brats</kid>
        <kid>brats</kid>
    </child>
</parent>

xslt:
Code:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="text" encoding="utf-8"/>

    <xsl:template match="/">
        <xsl:apply-templates/>
        <xsl:text>#xA;#xA;</xsl:text>
        <xsl:apply-templates>
            <xsl:with-param name="rtf-test" select="parent/child/children"/>
        </xsl:apply-templates>
    </xsl:template>

    <xsl:template match="parent">
        <xsl:param name="rtf-test" select="child/*"/>
        <xsl:apply-templates select="$rtf-test" mode="rtf"/>
    </xsl:template>

    <xsl:template match="children" mode="rtf">
        <xsl:value-of select="."/>
        <xsl:if test="position() != last()">, </xsl:if>
    </xsl:template>

</xsl:stylesheet>


output:
Code:
kid A, kid B, kid C, kid D, bratsbratsbrats

kid A, kid B, kid C, kid D
Needless to say, this intrigued me. A lot. (Some of us aren't fortunate enough to have access to an XSLT 2.0 processor at work yet. T_T) But this works in all the 1.0 processors I've tried, and I can't find more explicit information about it. The original stylesheet is only a few weeks old, but I suspect the concept has been around for a lot longer.

So... concerning result-tree-fragments vs. node-sets, I now assume the only differences are:
1) you can't apply xpath expressions when selecting what nodes to apply the templates to - it's a one-shot apply from the root node on downward
2) you have to make damn sure that your templates matching a root-node know exactly what they're doing, or otherwise it'll catch the variable's root. (i.e. always start with <xsl:template match="/document-root-node"> rather than <xsl:template match="/">, or always use a mode like so: <xsl:apply-templates select="$rtf-to-traverse" mode="rtf"/>)



In the basic example I've made, and even in the FizzBuzz example, it's not really worth arguing, seeing that one could simply use a key to achieve the same thing. However, when you can continue and apply this to variables consisting of complex node-sets, nested parameter calls, and so on with the freedom of XSLT 2.0 (only a lot more controlled and RTF-aware) - it sounds like it could open up a lot of doors for those of us still confined to XSLT 1.0.

Anything I'm mistaken about here? I'd like to know of any shortcomings in my logic before I start relying on this functionality in the future.
 
Old March 26th, 2007, 04:21 PM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

I don't see a result tree fragment anywhere in your stylesheet. Result tree fragments are created when you have an xsl:variable, xsl:with-param, or xsl:param element with child instructions.

Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
 
Old March 26th, 2007, 07:09 PM
Registered User
 
Join Date: Mar 2007
Posts: 2
Thanks: 0
Thanked 0 Times in 0 Posts
Send a message via AIM to korisu
Default

Quote:
quote:Originally posted by mhkay
I don't see a result tree fragment anywhere in your stylesheet. Result tree fragments are created when you have an xsl:variable, xsl:with-param, or xsl:param element with child instructions.
Gotcha; I had known that variable/param/with-param content was treated as a RTF, but all of the documentation I've seen so far has been really dodgy on what the content is treated as if there's an XPath expression in the select attribute. So if I keep it constrained to variables and parameters that pass node-sets, I can legally perform the RTF-forbidden XPath operators on them?

 
Old March 27th, 2007, 02:11 AM
joefawcett's Avatar
Wrox Author
 
Join Date: Jun 2003
Posts: 3,074
Thanks: 1
Thanked 38 Times in 37 Posts
Default

If you use the select attribute to specify the contents of a variable, param or with-param then you'll have no problems. Unfortunately some content is too complex to create in this way and, in version 1.0 at least, you're forced to use the node-set extension function.

--

Joe (Microsoft MVP - XML)





Similar Threads
Thread Thread Starter Forum Replies Last Post
Exclude Elements in Apply Templates mail4kaja XSLT 18 November 29th, 2008 12:09 PM
question on xslt templates -- urgent subbukns XSLT 1 May 21st, 2007 05:17 PM
Templates Won't Apply neilac333 XSLT 5 October 26th, 2006 01:39 PM
simple XSLT question _thinking XSLT 4 January 24th, 2006 10:41 AM
Simple question about XSLT bertcox XSLT 2 May 5th, 2004 09:31 AM





Powered by vBulletin®
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
Copyright (c) 2020 John Wiley & Sons, Inc.