Re: [xsl] template in template? (references)

Subject: Re: [xsl] template in template? (references)
From: Jeni Tennison <mail@xxxxxxxxxxxxxxxx>
Date: Fri, 15 Jun 2001 15:53:09 +0100
Hi Daniel,

> well, i'm wondering if it's possible to use sth like following:
> <xsl:template match="ref">
>    <link href="@id"> go to ref </link>
> </xsl:template>
> <xsl:template match="link">
>    <a href="@href"><xsl:apply-templates/></link>
> </xsl:template>

Yes, that's legal XSLT (well, once you replace the </link> in the
second template with </a> to make it well formed), but it might not
give you the result that you're after.  Given the source:

   <ref id="foo" />

The above will generate:

<link href="@id"> go to ref </link>

The first template matches the ref element and generates a link
element with an href attribute equal to the value "@id" and with a
value of ' go to ref '.

It think it's likely that you were hoping that it would produce:

<a href="foo"> go to ref </a>

If so, there are two things that are stopping it.  The first is that
you've forgotten the {}s in the attribute value template - you wanted:

   <link href="{@id}"> go to ref </link>

to get the value of the id attribute on the ref element into the value
of the href attribute on the link element that you're creating.

The second problem is deeper - XSLT doesn't go on to process the stuff
that it generates, it only goes through the source tree (or any other
documents you tell it to access).  However, there's a way around that
if you want to do it, using a node-set() extension function (versions
are available in most XSLT processors).  To get the stylesheet to
create the link element and then process that, use:

<xsl:template match="ref">
   <!-- create a variable called $link-rtf holding the result tree
        fragment that you're generating -->
   <xsl:variable name="link-rtf">
      <link href="{@id}"> go to ref </link>
   <!-- tell the processor to apply templates to the content of
        that result tree fragment, converted to a node set -->
   <xsl:apply-templates select="exsl:node-set($link-rtf)/*" />

> and btw. is there any simple cross-referencing solution in xsl? i
> tried sth with id(), but i can't make it work.

Assuming you're generating HTML, you usually want one template that
matches whatever node you're generating the reference from and
produces the *content*, and one template that matches the same node to
produce the *reference*.  Usually you use two modes for this; one
creates an anchor (an a element with a name attribute) and the other
creates a link (an a element with a href attribute):

<xsl:template match="ref" mode="content">
   <a name="{@id}">[anchor]</a>
   <xsl:apply-templates />

<xsl:template match="ref" mode="reference">
   <a href="#{@id}">[reference]</a>
   <xsl:apply-templates />

You'll have to apply templates in the different modes to get the
different kind of content.

If you haven't got any ids that you can use as IDs for the anchors,
then you can generate your own with generate-id().

I hope this all helps,


Jeni Tennison

 XSL-List info and archive:

Current Thread