all groups > dotnet xml > july 2004 >
You're in the

dotnet xml

group:

node-sets not sent to xslt extension object correctly



node-sets not sent to xslt extension object correctly Douglas Steen
7/11/2004 11:20:40 PM
dotnet xml: Here's what I have (in snippets)
** XML **
<parent>
<child>
<grandchild/>
</child>
</parent>

** XSLT **
<xsl:template match="/parent">
parent: <xsl:value-of select="util:LocalName(.)"/>
child: <xsl:value-of select="util:LocalName(child)"/>
grandchild: <xsl:value-of select="util:LocalName(child/grandchild)"/>
</xsl:template>

** C# (util object) **
public string LocalName(XmlPathNodeIterator xit)
{
return xit.Current.LocalName;
}

but for some reason, each call to LocalName returns "parent". A little
sleuthing, and I've discovered that the XmlPathNodeIterators _are_
different: they seem to have different FilterQuery and ChildrenQuery
internal settings, but how do I translate that into something I can have
access to?

Thanks,
Douglas R. Steen
Boulder, CO

Re: node-sets not sent to xslt extension object correctly Douglas Steen
7/12/2004 6:27:48 AM
Thanks, Oleg, but when I try that with the first example (XSLT:
select="util:LocalName(.)") it returns false and .Current becomes null.
It's as if, in the first example, the iterator has already been "moved". Is
it that calling the extension object with (.) sends the XPathNodeIterator
with a single node, whereas calling it with (child) sends a nodeset? If so,
is there a way of telling that MoveNext is going to move me off the end of
the set, before I move? (Or, even better, changing my XSLT so that I can be
sure that a single node is sent? I've tried /child[0] and /child/node() to
no avail.)

Thanks alot for the help.

[quoted text, click to view]

Re: node-sets not sent to xslt extension object correctly Douglas Steen
7/12/2004 8:17:11 AM
I'm using a rather complicated extension object (rather than doing it
inline), and in simplifying for this post, I may have gone too far. I used
your example and got the same results, but when I tried to add some of the
initial complexity, I ran into the problem again. While the example below
works, this one doesn't:

<xsl:template match="/parent">
<xsl:for-each select="child">
parent: <xsl:value-of select="util:LocalName(../parent)"/>
child: <xsl:value-of select="util:LocalName(.)"/>
grandchild: <xsl:value-of select="util:LocalName(./grandchild)"/>
</xsl:for-each>
</xsl:template>

Thoughts?

Thanks for taking the time on this


[quoted text, click to view]

Re: node-sets not sent to xslt extension object correctly Douglas Steen
7/12/2004 8:24:43 AM
On a hunch, I tried this:

<xsl:template match="/parent">
<xsl:variable name="parentNode" select="."/>
<xsl:for-each select="child">
parent: <xsl:value-of select="util:LocalName($parentNode)"/>
child: <xsl:value-of select="util:LocalName(.)"/>
grandchild: <xsl:value-of select="util:LocalName(./grandchild)"/>
</xsl:for-each>
</xsl:template>

and it _does_ work. Whereas calling the parent directly (..) doesn't?

Alright, now I've got something I can use; thanks for all your help. If you
(or anyone else) wants to clear up what's going on here, I'd love to
understand this better, but I can move forward now & I thank you.

[quoted text, click to view]

Re: node-sets not sent to xslt extension object correctly Oleg Tkachenko [MVP]
7/12/2004 10:51:39 AM
[quoted text, click to view]

You have to call MoveNext() on XPathNodeIterator each time you want next
node:

public string LocalName(XPathNodeIterator xit)
{
if (xit.MoveNext())
return xit.Current.LocalName;
else
return "";
}

--
Oleg Tkachenko [XML MVP]
Re: node-sets not sent to xslt extension object correctly Oleg Tkachenko [MVP]
7/12/2004 4:40:02 PM
[quoted text, click to view]

Sorry, I can't reproduce the problem. Here is the stylesheet:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:util="urn:my-scripts">
<msxsl:script language="C#" implements-prefix="util"><![CDATA[
public string LocalName(XPathNodeIterator xit)
{
return xit.MoveNext()? xit.Current.LocalName : "";
}
]]>
</msxsl:script>
<xsl:template match="/parent">
parent: <xsl:value-of select="util:LocalName(.)"/>
child: <xsl:value-of select="util:LocalName(child)"/>
grandchild: <xsl:value-of select="util:LocalName(child/grandchild)"/>
</xsl:template>
</xsl:stylesheet>

When applied to your XML it outputs:

parent: parent
child: child
grandchild: grandchild

--
Oleg Tkachenko [XML MVP]
AddThis Social Bookmark Button