This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
Re: Re: RE: syntax sugar for call-template
- To: Dimitre Novatchev <dnovatchev at yahoo dot com>
- Subject: Re: [xsl] Re: RE: syntax sugar for call-template
- From: Jeni Tennison <mail at jenitennison dot com>
- Date: Fri, 16 Feb 2001 16:44:04 +0000
- CC: xsl-list at lists dot mulberrytech dot com
- Organization: Jeni Tennison Consulting Ltd
- References: <20010216154020.18994.qmail@web6304.mail.yahoo.com>
- Reply-To: xsl-list at lists dot mulberrytech dot com
Hi Dimitre,
> Then this is a good use case, which shows that we need the following:
>
> <xsl:reference-of select="$xpathExpression"/>
>
> This is the counterpart of xsl:copy-of. For each node in
> $xpathExpression its reference will be generated.
>
> By definition, a node-set containing references ("reference-set"???)
> will be indistinguishable from a nodeset containing the original
> nodes.
Interesting idea, although I think it should be thought of as a way of
building up a node set without introducing a new data type to XSLT (or
to the XML Information Set!).
If you made it *only* valid within variable-setting content (i.e. in
xsl:variable, xsl:param and xsl:with-param) you would avoid the
question of what to do if it occurred outside such a context. The
trouble is that you can't tell whether the content of a template is
going to be outputted to the result tree or held in a variable. How
should a (reference to a) source tree node be outputted to the result
tree?
And you would probably have to say that if a xsl:reference-of is used
then you could have no other node-generating content. Otherwise you
end up with node sets containing nodes from the source trees mixed
with new nodes from no tree or something. Or would it be a RTF with
source nodes mixed with result nodes?
So with those restrictions I could do:
<xsl:variable name="unique-nodes">
<xsl:for-each select="$nodes[count(.|key($key, .)[1]) = 1]">
<xsl:reference-of select="." />
</xsl:for-each>
</xsl:variable>
rather than:
<xsl:variable name="unique-nodes"
select="$nodes[count(.|key($key, .)[1]) = 1]" />
[Actually it's possibly more useful than this, coming into its own
when constructing irregular node sets, because there can be multiple
xsl:for-eaches, xsl:ifs and so on in there as well - this is a pretty
simple case.]
However, placing those restrictions on it unfortunately makes it
pretty pointless in this case - I can build up the node set, but still
not return it as a node set: I need xsl:return to do that. And with
xsl:return, I could just do:
<xsl:key name="default-key" match="node()" use="." />
<xsl:template name="my:distinct">
<xsl:param name="nodes" select="/.." />
<xsl:param name="key" select="'default-key'" />
<xsl:return select="$nodes[count(.|key($key, .)[1]) = 1]" />
</xsl:template>
with no reason to build the node set anyway.
If you look at the intersection function, things are slightly more
interesting. With just xsl:return I think you have to use recursion:
<xsl:template name="my:intersection">
<xsl:param name="nodeset1" select="/.." />
<xsl:param name="nodeset2" select="/.." />
<xsl:choose>
<xsl:when test="$nodeset1">
<xsl:variable name="rest"
select="my:intersection($nodeset[position() > 1],
$nodeset2)" />
<xsl:return select="$nodeset1[1][count(.|$nodeset2) =
count($nodeset2)] |
$rest" />
</xsl:when>
<xsl:otherwise>
<xsl:return select="/.." />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
With xsl:reference-of as well, you could do it within an xsl:for-each:
<xsl:template name="my:intersection">
<xsl:param name="nodeset1" select="/.." />
<xsl:param name="nodeset2" select="/.." />
<xsl:return>
<xsl:for-each select="$nodeset1">
<xsl:if test="count(.|$nodeset2) = count($nodeset2)">
<xsl:reference-of select="." />
</xsl:if>
</xsl:for-each>
</xsl:return>
</xsl:template>
Cheers,
Jeni
---
Jeni Tennison
http://www.jenitennison.com/
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list