This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
Re: Implementing XPointer Resolution With saxon:evaluate()
- From: Jeni Tennison <jeni at jenitennison dot com>
- To: "W. Eliot Kimber" <eliot at isogen dot com>
- Cc: XSL List <xsl-list at lists dot mulberrytech dot com>
- Date: Tue, 13 Aug 2002 22:50:54 +0100
- Subject: Re: [xsl] Implementing XPointer Resolution With saxon:evaluate()
- Organization: Jeni Tennison Consulting Ltd
- References: <3D5975B7.D3F4837@isogen.com>
- Reply-to: xsl-list at lists dot mulberrytech dot com
Hello Eliot :)
> In my test style sheet I am generating an HTML page that makes
> explicit both the resolved links from the initial references to
> their ultimate targets as well as each of the intermediate steps
> through the indirectors. To express the linkages in HTML I'm using
> the normal generate-id() approach in the output:
>
> <xsl:text>ID of ultimate target: </xsl:text>
> <xsl:variable name="members">
> <xsl:call-template name="resolve-xpointer"/>
> </xsl:variable>
> <xsl:for-each select="$members">
> <a href="#{generate-id()}"
> ><xsl:value-of select="generate-id()"
> /></a><xsl:text>, </xsl:text>
> </xsl:for-each>
>
> Where the "resolve-xpointer" template should resolve the xpointer in
> the href= attribute of the current node to a node set of ultimate
> targets. However, my implementation of resolve-xpointer uses
> xsl:copy-of, which of course isn't going to work because the copy
> nodes are not the same as the initial target nodes.
>
> What I can't figure out is how to have the resolve-xpointer template
> return the actual nodes referenced, not a copy of them--is this even
> possible without writing an extension function that does all the
> address resolution? That is, I don't see a way for the value of a
> template to be the direct value of a select action, rather than a
> copy of the value.
Yep, you're stuck. I can see two possible ways around the problem.
First option, since you're using extensions anyway, you could use
EXSLT's func:function to define a function for resolve-pointer. You
should be able to rejig the resolve-xpointer code so that it
recursively puts together a node-set rather than copying the nodes,
and then return that node set from the function, setting the variable
with:
<xsl:variable name="members" select="isogen:resolve-xpointer()" />
Second option, since the only information that you seem to be using
about these nodes is their generated ID, is to create a new set of
nodes whose values are the generated IDs of the nodes that you're
interested in. You can then turn the result tree fragment into a
node-set in the usual way in order to iterate over them:
<xsl:variable name="members">
<xsl:call-template name="resolve-xpointer"/>
</xsl:variable>
<xsl:for-each select="exsl:node-set($members)/*">
<a href="#{.}"><xsl:value-of select="." /></a>
<xsl:text>, </xsl:text>
</xsl:for-each>
Let us know if you need assistance with either of those.
> Also, why does this fail?:
>
> <xsl:for-each select="$direct-result">
> <xsl:choose>
> <xsl:when test="xindr:indirector">
> <!-- Never gets here -->
>
> When the context node is "xindr:indirector" (as returned by name())?
> The corresponding template match does work. Is this a subtle side
> effect of name-space processing?
>
> If I use test="name() = 'xindr:indirector'" then the when succeeds
> and I can verify that the addresses are getting resolved correctly
> and the indirection is being correctly recursed through.
I'm not quite sure, but could the difference be that when you do
test="xindr:indirector" you're testing whether the current node has a
*child* xindr:indirector element, but the name() function returns the
name of the current node? If you want to test whether the *current*
node is an xindr:indirector element, you need to use the self:: axis
explicitly:
<xsl:when test="self::xindr:indirector">
...
</xsl:when>
Cheers,
Jeni
---
Jeni Tennison
http://www.jenitennison.com/
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list