views:

21

answers:

1

I have an xslt stylesheet that needs to call a C# XSLT extension function in order to process a collection of elements. The code looks a little like this:

Xslt:

<xsl:apply-templates mode="MyTemplate" select="myextension:GetSomeCollection(@someattribute)" />
<xsl:template mode="MyTemplate" match="myroot">
  <xsl:value-of select="xpath" />...<xsl:value-of select="/xpath" />
</xsl:template>

Extension method:

public XPathNavigator GetSomeCollection(string Attribute)
{
    XmlDocument doc = new XmlDocument()
    //etc... 
    return doc.CreateNavigator();
}

The extension method returns a XPathNavigator as thats the only way I can see for an extension method to return any sort of collection.

The problem I'm having is that my template (the one with mode="MyTemplate") needs to be able to access xml nodes in the root / input document to the xslt stylesheet (as well as nodes in the node set returned by the extension method), however the template only seems to have access to the xml fragment returned by GetSomeCollection - xpath expressions starting / just resolve to the start of that fragment.

I can see why this is (the template is processing an xml fragment, however that fragment belongs to a different document), however I can't see how to get around it. There doesn't seem to be any way to get the extension method to produce an xml fragment belonging to the original document.

What can I do?

+2  A: 

Use a variable?

<xsl:variable name="root" select="/"/>
<xsl:template mode="MyTemplate" match="myroot">
  <xsl:value-of select="$root/..."/>
  <xsl:value-of select="xpath" />...<xsl:value-of select="/xpath" />
</xsl:template>

or a parameter:

<xsl:apply-templates mode="MyTemplate"
       select="myextension:GetSomeCollection(@someattribute)">
  <xsl:with-param name="foo" select="...some local query..."/>
</xsl:apply-templates>

<xsl:template mode="MyTemplate" match="myroot">
  <xsl:param name="foo"/>
  <xsl:value-of select="$foo/..."/>
  <xsl:value-of select="xpath" />...<xsl:value-of select="/xpath" />
</xsl:template>
Marc Gravell
@Marc Gravell: In the absence of input document, desired output or complete stylesheet, one can only guess. You could also use a node set union, for example: `apply-templates select="myextension:GetSomeCollection(@someattribute)|{...some local query..}"`
Alejandro
Thanks - this worked out quite well actually.
Kragen