tags:

views:

1249

answers:

3

I want something like this:

<msxsl:script language="C#">
   ??? getNodes() { ... return ... }
</msxsl:script>

<xsl:for-each select="user:getNodes()">
    ...
</xsl:for-each>

What return type should i use for getNodes() and what should i put in it's body?

+1  A: 

A quick google for C# xslt msxml revealed a link to the following page which gives many examples of extending XSLT in microsoft environments.

http://msdn.microsoft.com/en-us/magazine/cc302079.aspx

Specifically the section on Mapping Types between XSLT and .Net gives you exactly the information you need:

W3C XPath Type - Equivalent .NET Class (Type)

  • String - System.String
  • Boolean - System.Boolean
  • Number - System.Double
  • Result Tree Fragment - System.Xml.XPath.XPathNavigator
  • Node Set - System.Xml.XPath.XPathNodeIterator

So in your example I would try XPathNodeLiterator.

samjudson
+1 vote for partial answer.
Constantin
+1  A: 

I also have the same problem, in moving from MSXML to .NET native XSLT processing.

There is a bug in .NET 2.0 that makes it impractical to use:

<msxsl:script implements-prefix="user" language="jscript">
<![CDATA[
    function selectNodes(nsetCtxt, strExpr)
    {
     // Evaluating strExpr must result in a node-set(unfortunately there is currently no evalExpr method on the MSDOM)
     // If strExpr is not specified then just try to search for anything.
     if (strExpr == '') strExpr='zzz_will_not_be_found_zzz';

     return nsetCtxt.nextNode().selectNodes(strExpr);
    }
]]>
</msxsl:script>

and use compiled XSLT (it memory leaks HUGE) (http://blogs.msdn.com/tess/archive/2006/02/15/532804.aspx for one example)

I've attempted to use the XSLT C# extension object but can't quite work out how to replicate the same functionality:

<xsl:value-of select="user:selectNodes( //xml, concat('', @pagecontent_xpath) )"/>

where @pagecontent_xpath stores an xpath reference back to the XML document.

<xsl:variable name="pagecontent_xpath">rs_data/z_row[@dataset='customers']</xsl:variable>

This problem is effectively preventing me migrating my sites from classic ASP to .NET

Any thoughts?

Guy
+2  A: 

Hi Constantin,

In principle you need to use the XPathNodeIterator to return node sets (as Samjudson says). I take it that the example you gave is a degenerated function, as you do not supply it with any parameters. However, I think it is instructive the see how you could fabricate nodes out of thin air.

<msxsl:script language="C#">
   XPathNodeIterator getNodes() 
   { 
      XmlDocument doc = new XmlDocument();
      doc.PreserveWhitespace = true;
      doc.LoadXml("<root><fld>val</fld><fld>val2</fld></root>");
      return doc.CreateNavigator().Select("/root/fld");
   }
</msxsl:script>

However, typically you would want to do something in your function that is not possible in xslt, like filtering a node set based on some criteria. A criteria that is better implemented through code or depends om some external data structure. Another option is just that you would to simplify a wordy expression (as in the example bellow). Then you would pass some parameters to you getNodes function. For simplicity I use a XPath based filtering but it could be anything:

   <msxsl:script language="C#">
       XPathNodeIterator getNodes(XPathNodeIterator NodesToFilter, string Criteria)
      {
         XPathNodeIterator x = NodesToFilter.Current.Select("SOMEVERYCOMPLEXPATH["+Criteria+"]");
         return x;
      }
   </msxsl:script>
   <xsl:for-each select="user:getNodes(values/val,'SomeCriteria')">
    ...
  </xsl:for-each>

Hopes this helps, Boaz

Boaz