HOW TO: Implement and Use Custom Extension Functions When You Execute XPath Queries in Visual C# .NET (324462)



The information in this article applies to:

  • Microsoft Visual C# .NET (2003)
  • Microsoft Visual C# .NET (2002)
  • Microsoft XML Classes (included with the .NET Framework 1.0)
  • Microsoft XML Classes (included with the .NET Framework 1.1)

This article was previously published under Q324462

SUMMARY

Non-standard user-defined functions that are used in XML Path Language (XPath) query expressions are referred to as XPath extension functions. You may want to implement a custom XPath extension function when the standard XPath functions do not address a specific requirement.

The Microsoft .NET Framework provides interfaces that you can use to implement and to use custom extension functions and user-defined variables in XPath expressions that are used to execute XPath queries in .NET applications. The XsltContext class, the IXsltContextFunction interface, and the IXsltContextVariable interface are all implemented in the System.Xml.Xsl namespace and are the .NET Framework components that you can use to address this requirement.

This step-by-step article describes how to use these interfaces and provides a code sample to illustrate their application in implementing and in using extension functions and user-defined variables in XPath expressions.

back to the top

Role of XsltContext

The .NET Framework XPath processor (which the XPathNavigator class in the System.Xml.XPath namespace implements) uses an XsltContext object to resolve references to unknown functions and variables that it finds in XPath query expressions.

You must implement and associate a custom XsltContext object with the XPathNavigator object that is used to execute XPath queries to resolve references to user-defined extension functions and variables in the query expressions. The XsltContext class, the IXsltContextFunction interface, and the IXsltContextVariable interface are the .NET Framework components that you use to implement this custom execution context. These components are implemented in the System.Xml.Xsl namespace. They are the application programming interface (API) elements that constitute the core interface between the .NET Framework XPath and the XSL transformation (XSLT) processors to resolve references to user-defined extension functions and variables in XPath query expressions that are used in XSLT style sheets.

Microsoft recommends that you use XSLT extension objects and inline script blocks to implement user-defined extension functions that are referenced in XPath query expressions that are used in XSLT style sheets. For additional information about implementing and using XSLT extension objects, click the article number below to view the article in the Microsoft Knowledge Base:

323370 HOW TO: Use Extension Objects When You Execute XSL Transformations in Visual C# .NET Applications

Microsoft recommends that you implement a custom XsltContext object to resolve references to user-defined extension functions and variables in XPath query expressions only when you programmatically execute XPath queries in .NET applications by using an XPathNavigator object.

To implement a custom XsltContext class, you can inherit from the XsltContext abstract base class that is implemented in the System.Xml.Xsl namespace. You can then use an object instance of the custom XsltContext class to encapsulate the execution context of the XPath processor and to resolve references to user-defined extension functions and variables in XPath query expressions.

The ResolveFunction and the ResolveVariable methods are the two key methods of the XsltContext abstract base class that you must override to implement the custom resolution functionality. The XPath processor calls these methods of the custom XsltContext object at run time to resolve references to user-defined extension functions and variables in XPath query expressions. You must implement the ResolveFunction method to return a custom IXsltContextFunction object that can the XPath processor can use to resolve references to user-defined extension functions. Similarly, you must implement the ResolveVariable method to return a custom IXsltContextVariable object that the XPath processor can use to resolve references to user-defined variables.

back to the top

Role of IXsltContextFunction

The XPath processor uses an IXsltContextFunction object at run time to resolve references to user-defined functions in XPath query expressions. This is an object instance of a custom class that implements the IXsltContextFunction interface that is defined in the System.Xml.Xsl namespace.

The custom IXsltContextFunction object that the XPath processor uses to resolve references to extension functions must implement the user-defined functions that are used in an XPath query expression. The instance of the custom IXsltContextFunction object to use must be returned by the ResolveFunction method of the custom XsltContext that is associated with the XPath processor.

At run time, the Invoke method of the custom IXsltContextFunction object that the custom XsltContext object supplies is executed to resolve references to extension functions in XPath query expressions.

back to the top

Role of IXsltContextVariable

The XPath processor uses an IXsltContextVariable object at run time to resolve references to user-defined variables in XPath query expressions. This is an object instance of a custom class that implements the IXsltContextVariable interface that is implemented in the System.Xml.Xsl namespace.

The instance of the custom IXsltContextVariable object to use must be returned by the ResolveVariable method of the custom XsltContext object that is associated with the XPath processor.

The Evaluate method of the IXsltContextVariable object that the custom XsltContext object supplies is executed to resolve references to user-defined variables in XPath query expressions.

back to the top

Resolve User-defined Extension Functions and Variables (Process Flow Diagram)

The following diagram is a process flow diagram that depicts the use of custom XsltContext, IXsltContextFunction, and IXsltContextVariable objects to resolve user-defined extension functions and variables that are found in an XPath query expression. This illustration uses the EvaluateXPathNavigator method to execute an XPath query whose expression references a user-defined extension function and a user-defined variable. Keep in mind the following key points:
  • You must implement a custom XsltContext object and then associate this custom XsltContext object with the XPath processor to resolve references to user-defined extension functions and variables in XPath expressions.
  • The ResolveFunction method of the custom XsltContext object is executed to resolve a reference to a user-defined extension function. This method returns an object instance of a custom IXsltContextFunction class that implements the extension function. The XPath processor executes the Invoke method of the IXsltContextFunction object that is returned to resolve and to execute the function.
  • The ResolveVariable method of the custom XsltContext object is executed to resolve a reference to a user-defined variable. This method returns an object instance of a custom IXsltContextVariable class. The XPath processor executes the Evaluate method of the custom IXsltContextVariable class to access the value of the variable.
back to the top

Create the Sample Visual C# .NET Application

This section describes how to create a sample Visual C# .NET Console Application project that illustrates how to implement and how to use custom XsltContext, IXsltContextFunction, and IXsltContextVariable classes to resolve references to extension functions and user-defined variables in XPath query expressions.

To create the sample application, follow these steps:
  1. To create a new Console Application in Visual C# .NET, follow these steps:
    1. Start Microsoft Visual Studio .NET.
    2. On the File menu, point to New, and then click Project.
    3. In the New Project dialog box, click Visual C# Projects under Project Types, and then click Console Application under Templates.
    4. In the Name box, type XPathExtensionFunctions.
  2. Use the following XML to create and to add an XML document that is named Books.xml to the project. The XPath queries in the sample application access the data in this document.
    <?xml version="1.0" encoding="utf-8" ?> 
    <Books>
    	<Title>A Brief History of Time</Title>
    	<Title>Principle Of Relativity</Title>
    </Books>
    					
  3. Add the following using directives at the top of Class1.cs:
    using System;
    using System.Xml;
    using System.Xml.XPath;
    using System.Xml.Xsl;
    					
  4. In the next four steps, you incrementally add code to implement the following items:
    • The Main() method that contains the client code to execute XPath queries whose expressions reference user-defined extension functions and a user-defined variable
    • A custom XsltContext class
    • A custom IXsltContextFunction class
    • A custom IXsltContextVariable class
    Add the following code to implement the Main() method in Class1.cs:
          static void Main(string[] args)
          {
             try
             {
                // Load source XML into an XPathDocument object instance.
                XPathDocument xmldoc = new XPathDocument("books.xml");
                // Create an XPathNavigator from the XPathDocument.
                XPathNavigator nav = xmldoc.CreateNavigator();
    
                // The user-defined functions in this sample implement equivalents of the frequently-used
                // Left(string,length) and Right(string,length) Visual Basic string functions.
    
                // Compile two XPath query expressions that use the user-defined XPath functions and a user-defined variable.
                // The compilation step only checks the query expression for correct tokenization. It does not 
                // try to resolve or to verify the definition or validity of the function and the variable names
                // that are used in the query expression.
                XPathExpression expr1 = nav.Compile("myFuncs:left(string(.),$length)");
                XPathExpression expr2 = nav.Compile("myFuncs:right(string(.),$length)");
    
                // Create an instance of an XsltArgumentList object.
                XsltArgumentList varList = new XsltArgumentList();
                // Add the user-defined variable to the XsltArgumentList object,
                // and then supply a value for it.
                varList.AddParam("length", "", 5);
    
                // Create an instance of a custom XsltContext object. This object is used to 
                // resolve the references to the user-defined XPath extension functions and the
                // user-defined variable at execution time. 
    
                // Notice that in the Ctor, you also pass in the XsltArgumentList object 
                // in which the user-defined variable is defined.
                CustomContext cntxt = new CustomContext(new NameTable(), varList);
    
                // Add a namespace definition for the ns prefix that qualifies the user-defined 
                // function names in the expr1 and expr2 query expressions.
                cntxt.AddNamespace("myFuncs", "http://myXPathExtensionFunctions");
    
                // Associate the custom XsltContext object with the two XPathExpression objects
                // whose query expressions use the custom XPath functions and the custom variable.
                expr1.SetContext(cntxt);
                expr2.SetContext(cntxt);
    
                // Create an instance of an XPathNodeIterator object to iterate through all the Title nodes
                // in the source XML.
                XPathNodeIterator iter = nav.Select("/Books/Title");
                while(iter.MoveNext())
                {
                    // Write the full content of the current title element node.
                    Console.WriteLine("Title : " + iter.Current.Value);
                    // Apply XPathExpression expr1 to the current title element node
                    // to extract and to display the first five characters.
                    // The value is supplied for the length variable. [myFuncs:left(.,$length)]
                    Console.WriteLine("\tleft() : " + iter.Current.Evaluate(expr1));
                    // Apply XPathExpression expr2 to the current title element node
                    // to extract and to display the last five characters.
                    // The value is supplied for the length variable. [myFuncs:right(.,$length)]
                    Console.WriteLine("\tright() : " + iter.Current.Evaluate(expr2));
                 }
             }
             catch(Exception ex)
             {
                Console.WriteLine(ex.Message);
             }
             Console.ReadLine();
          }
    						
    Note For more information about the code in this step, see the "Code in Step 4" section of this article.
  5. Add the following code after the definition of Class1 in Class1.cs to implement the custom IXsltContext class:
       class CustomContext : System.Xml.Xsl.XsltContext
       {
          // XsltArgumentList to store definitions (names and values) of user-defined variables
    
          // that can be accessed by XPath query expressions that are evaluated by using an object instance
          // of this class as the XsltContext. 
          private XsltArgumentList m_ArgList;
    
          // Implement constructors.
          public CustomContext()
          {
          }
    
          public CustomContext(NameTable nt, XsltArgumentList args) : base (nt)
          {
             m_ArgList = args;
          }
    
          // Function to resolve references to user-defined XPath extension functions in XPath query 
          // expressions that are evaluated by using an object instance of this class as the XsltContext. 
    
          // This function creates and returns an instance of the XPathExtensionFunctions custom class 
          // that implements the IXsltContextFunction interface. 
          public override System.Xml.Xsl.IXsltContextFunction ResolveFunction(string prefix, string name, System.Xml.XPath.XPathResultType[] ArgTypes)
          {
             XPathStringExtensionFunctions func = null;
             const int MINARGS = 2, MAXARGS = 2;
             if (name == "left")
                // Create an instance of an XPathStringExtensionObjects class by supplying parameters  
                // that map to the user-defined XPath extension function left(). The Invoke method 
                // of the returned object will be used at run time to execute the left() function.
                func = new XPathStringExtensionFunctions(MINARGS, MAXARGS, XPathResultType.String, null, "left");
             else if (name == "right")
                // Create an instance of an XPathStringExtensionObjects class by supplying parameters 
                // that map to the user defined XPath extension function right(). The Invoke method 
                // of the returned object will be used at run time to execute the right() function.
                func = new XPathStringExtensionFunctions(MINARGS, MAXARGS, XPathResultType.String, null, "right");
    
             // Return the XPathStringExtensionFunctions object instance.
             return func;
          }
    
          // Function to resolve references to user-defined XPath extension variables in XPath query.
          public override System.Xml.Xsl.IXsltContextVariable ResolveVariable(string prefix, string name)
          {
             // Create an instance of an XPathExtensionVariable (custom IXsltContextVariable
             //  implementation) object by supplying the name of the user-defined variable to resolve.
             XPathExtensionVariable Var;
             Var = new XPathExtensionVariable(name);
    
             // Return the XPathExtensionVariable object instance that was created. The Evaluate method of the 
             // returned object will be used at run time to resolve the user-defined variable 
             // that is referenced in the XPath query expression. 
             return Var;
          }
    
    
    
          public override bool PreserveWhitespace(System.Xml.XPath.XPathNavigator node)
          {
             return Convert.ToBoolean(null); // empty implementation, returns false
          }
    
          public override int CompareDocument(string baseUri, string nextbaseUri)
          {
             return Convert.ToInt32(null); // empty implementation, returns 0
          }
    
          public override bool Whitespace
          {
             get 
             { 
                return true;
             }
          }
    
          // Returns the XsltArgumentList that contains the user-defined variable definitions (names and values). 
          // This property is accessed by the Evaluate method of the XPathExtensionVariable object instance
          // that the ResolveVariable method of this class returns to resolve references to user-defined variables 
          // in XPath query expressions. 
          public XsltArgumentList ArgList
          {
             get
             { 
                return m_ArgList;
             }
          }
       }
    						
    Note For more information about the code in this step, see the "Code in Step 5" section of this article.
  6. Add the following code after the definition of the custom XsltContext class in Class1.cs to implement the custom IXsltContextFunction class:
       // An object instance of this class is used as an interface
       // to resolve and to execute a specified user-defined function. 
       public class XPathStringExtensionFunctions : System.Xml.Xsl.IXsltContextFunction
       {
          // The data types of the arguments that are passed to the custom XPath extension function
          // that an object instance is used to execute
          private System.Xml.XPath.XPathResultType[] m_ArgTypes;
          // The minimum number of arguments that must be passed to a custom XPath extension function 
          // that an object instance is used to execute
          private int m_MinArgs;
          // The maximum number of arguments that must be passed to a custom XPath extension function 
          // that an object instance is used to execute
          private int m_MaxArgs;
          // The data type of the return value of a custom XPath extension function 
          // that an object instance is used to execute
          private System.Xml.XPath.XPathResultType m_ReturnType;
          // The name of the custom XPath extension function that an object instance is used to execute
          private string FunctionName;
    
          // Constructor that is used in the ResolveFunction method of the custom XsltContext class (CustomContext) 
          // to create and to return an instance of the IXsltContextFunction object to execute a specified 
          // user-defined XPath extension function at run time.
          public XPathStringExtensionFunctions(int p_minArgs, int p_maxArgs, XPathResultType p_ReturnType, XPathResultType[] p_ArgTypes, string p_FunctionName)
          {
             this.m_MinArgs = p_minArgs;
             this.m_MaxArgs = p_maxArgs;
             this.m_ReturnType = p_ReturnType;
             this.m_ArgTypes = p_ArgTypes;
             this.FunctionName = p_FunctionName;
          }
    
          // Readonly property methods to access the private fields
          public System.Xml.XPath.XPathResultType[] ArgTypes
          {
             get
             {
                return m_ArgTypes;
             }
          } 
          public int Maxargs
          {
             get
             {
                return m_MaxArgs;
             }
          }
        
          public int Minargs
          {
             get
             {
                return m_MaxArgs;
             }
          }
    
          public System.Xml.XPath.XPathResultType ReturnType
          {
             get
             {
                return m_ReturnType;
             }
          }
    
          // The two custom XPath extension functions
          private string left(string str, int length)
    
          {
             return str.Substring(0, length);
          }
    
          private string right(string str, int length)
          {
             return str.Substring((str.Length - length), length);
          }
    
          // Function to execute a specified user-defined XPath extension function at run time
          public object Invoke(System.Xml.Xsl.XsltContext xsltContext, object[] args, System.Xml.XPath.XPathNavigator docContext)
          {
             string str = null;
             if (FunctionName == "left")
                str = left(Convert.ToString(args[0]), Convert.ToInt32(args[1]));
             else if (FunctionName == "right")
                str = right(Convert.ToString(args[0]), Convert.ToInt32(args[1]));
             
             return (object) str;
          }
       }
    						
    Note For more information about the code in this step, see the "Code in Step 6" section of this article.
  7. Add the following code after the definition of the custom IXsltContextFunction class in Class1.cs to implement the custom IXsltContextVariable class:
       // This is the class that implements the System.Xml.Xsl.IXsltContextVariable interface.
       // This class is used to resolve references to user-defined variables in 
       // XPath query expressions at run time. An object instance of this class is created and returned
       // by the overridden ResolveVariable function of the custom XsltContext class (CustomContext).
       public class XPathExtensionVariable : IXsltContextVariable
       {
          // The name of the user-defined variable to resolve
          private string m_VarName;
    
          // Constructor used in the overridden ResolveVariable function of the custom XsltContext class (CustomContext).
          public XPathExtensionVariable(string VarName)
          {
             m_VarName = VarName;
          }
    
          // This is the function to return the value of the specified user-defined variable.
          // Uses the GetParam method of the XsltArgumentList property of the current active custom XsltContext
          // object to access and return the value assigned to the specified variable
          public object Evaluate(System.Xml.Xsl.XsltContext xsltContext)
          {
             XsltArgumentList vars = ((CustomContext) xsltContext).ArgList;
             return vars.GetParam(m_VarName, null);
          }
    
          // Is it a local XSLT variable? Not applicable when you are not using a style sheet.
          public bool IsLocal
          {
             get
             {
                return false;
             }
          }
    
          // Is it an XSLT parameter? Not applicable when you are not using a style sheet.
          public bool IsParam
          {
             get
             {
                return false;
             }
          }
    
          // The System.Xml.XPath.XPathResultType of the variable
          public System.Xml.XPath.XPathResultType VariableType
          {
             get
             {
                return XPathResultType.Any;
             }
          }
       }
    						
    Note For more information about the code in this step, see the "Code in Step 7" section of this article.
back to the top

Code Explanation

Code in Step 4

This code uses three XPath query expressions. The following query expression is executed first to retrieve all of the title nodes in the Books.xml file. This query expression does not reference any custom extension functions or user-defined variables:
/Books/Title
				
The following two query expressions use custom extension functions that mimic the Visual Basic Left string and Right string functions and a user-defined variable to extract a specified number of left-most and right-most characters from each title node that the first XPath query returns:
myFuncs:left(string(.),$length)
myFuncs:right(string(.),$length)
				
Custom XsltContext, IXsltContextFunction, and IXsltContextVariable objects are used to resolve the references to the extension functions and the user-defined variables.

This code first creates an instance of an XPathDocument object and then loads the data from Books.xml into the XPathDocument object. Then the code uses the CreateNavigator method of the XPathDocument object to execute the XPath queries against the data.
XPathDocument xmldoc = new XPathDocument("books.xml");
XPathNavigator nav = xmldoc.CreateNavigator();
				
Next, the code compiles the two query expressions that are applied to each of the title nodes in Books.xml to extract a specified number of left-most and right-most characters from the node value. Notice that these query expressions use the left and right custom XPath extension functions to extract the required characters. Also, notice that this code uses a user-defined variable named length to specify the number of characters to extract.
XPathExpression expr1 = nav.Compile("myFuncs:left(string(.),$length)");
XPathExpression expr2 = nav.Compile("myFuncs:right(string(.),$length)");
				
The code then creates an instance of an XsltArgumentList object, uses its AddParam method to define the length of the user-defined variable, and then supplies a value for it that will be used at run time when you execute the query expression. With an assigned value of 5, the five left-most and right-most characters are extracted from the value of each title node that the two query expressions are applied to.
XsltArgumentList varList = new XsltArgumentList();
varList.AddParam("length", "", 5);
				
This XsltArgumentList object is supplied as a parameter when you create an instance of the custom XsltContext object. A property of the custom XsltContext object is used to reference it (which will be clearer when you examine the code that is used to implement the custom XsltContext object). The custom XsltContext object that is associated with the XPathExpression object is passed as a parameter to the Evaluate method of the custom IXsltContextVariable object, which the XPath processor uses to resolve references to user-defined variables.
CustomContext cntxt = new CustomContext(new NameTable(), varList);
				
Next, the code adds a definition for the custom namespace prefix that is used to qualify the references to the extension functions in the query expressions:
cntxt.AddNamespace("myFuncs", "http://myXPathExtensionFunctions");
				
The code then associates the custom context with the XPathExpression objects that is used to execute the XPath query expressions that reference the extension functions and the user-defined variable:
expr1.SetContext(cntxt);
expr2.SetContext(cntxt);
				
To execute the actual XPath queries, the code first executes an XPath query by using the Select method of the XPathNavigator object to retrieve all of the title nodes in Books.xml:
XPathNodeIterator iter = nav.Select("/Books/Title");
				
The returned XPathNodeIterator is used to move through the returned node set. In the while loop, the value of the current title node is displayed, and the Evaluate method of the XPathNavigator is used to apply the two XPathExpression objects that extract the specified number of left-most and right-most characters from the node value. The data that is returned when you execute these expressions is also displayed in the Console window.
while(iter.MoveNext())
{
      Console.WriteLine("Title : " + iter.Current.Value);
      Console.WriteLine("\tleft() : " + iter.Current.Evaluate(expr1));
      Console.WriteLine("\tright() : " + iter.Current.Evaluate(expr2));
}
				
back to the top

Code in Step 5

In this code, a user-defined class named CustomContext implements the custom XsltContext object. The CustomContext class inherits from the abstract base class XsltContext, which is implemented in the System.Xml.Xsl namespace.

This class defines a private XsltArgumentList member that is used to hold a reference to the XsltArgumentList object. This XsltArgumentList object contains definitions of user-defined variables that the client code supplies. The client code creates an instance of an object of this custom context. This member is made accessible to external components through a public, read-only property named ArgList.

The code in the constructor that the client code uses assigns the XsltArgumentList object parameter that contains definitions for the user-defined variables to the private XsltArgumentList member named m_ArgList:
public CustomContext(NameTable nt, XsltArgumentList args) : base (nt)
{
    m_ArgList = args;
}
				
View the code in the overridden ResolveFunction and ResolveVariable methods that the XPath processor invokes when it encounters the user-defined extension functions and the user-defined variable in the XPath query expressions.

The code in the ResolveFunction method creates and returns an object instance of the custom IXsltContextFunction class named XPathStringExtensionFunctions. XPathStringExtensionFunctions defines and implements the user-defined functions named left and right that are referenced in the query expressions. The XPath processor uses the Invoke method of the returned IXsltContextFunction object to execute the extension functions.
public override System.Xml.Xsl.IXsltContextFunction ResolveFunction(string prefix, string name, System.Xml.XPath.XPathResultType[] ArgTypes)
{
   XPathStringExtensionFunctions func = null;
   const int MINARGS = 2, MAXARGS = 2;
   if (name == "left")
      func = new XPathStringExtensionFunctions(MINARGS, MAXARGS, XPathResultType.String, null, "left");
   else if (name == "right")
      func = new XPathStringExtensionFunctions(MINARGS, MAXARGS, XPathResultType.String, null, "right");

   return func;
}
				
The constructor that is used to create an instance of the custom IXsltContextFunction object takes parameters that specify values for the following items:
  • Minimum and maximum number of parameters
  • Parameter types
  • Type of result that is generated
  • Name of the extension function that must be resolved
The ResolveFunction method is called one time for each extension function that is referenced in a query expression, and the ResolveFunction method returns the IXsltContextFunction object instance that is required to resolve the reference.

The ResolveVariable method creates and returns an object instance of the custom IXsltContextVariable class named XPathExtensionVariable. XPathExtensionVariable is required to resolve references to user-defined variables in query expressions. The name of the variable to be resolved is supplied as the parameter when you create an instance of the IXsltContextVariable object. The XPath processor uses the Evaluate method of the returned IXsltContextVariable object to resolve the reference to a user-defined variable.
public override System.Xml.Xsl.IXsltContextVariable ResolveVariable(string prefix, string name)
{
   XPathExtensionVariable Var;
   Var = new XPathExtensionVariable(name);

   return Var;
}
				
The ResolveVariable method is called one time for each user-defined variable that is referenced in a query expression, and the ResolveVariable method returns the IXsltContextVariable object instance that is required to resolve the reference.

Note that the methods that are specific to XSLT (PreserveWhitespace and CompareDocument) have no implementation. Microsoft recommends that you use XSLT extension objects or inline script blocks to implement extension functions for XPath queries in XSLT style sheets.

back to the top

Code in Step 6

The XPathStringExtensionFunctions class implements the IXsltContextFunction interface that is defined in the System.Xml.Xsl namespace.

The private members directly map to the parameters that are passed in when an object instance of this class is created in the ResolveFunction method of the custom XsltContext class. The code in its constructor assigns the parameters that are passed in to these private members:
public XPathStringExtensionFunctions(int p_minArgs, int p_maxArgs, XPathResultType p_ReturnType, XPathResultType[] p_ArgTypes, string p_FunctionName)
{
   this.m_MinArgs = p_minArgs;
   this.m_MaxArgs = p_maxArgs;
   this.m_ReturnType = p_ReturnType;
   this.m_ArgTypes = p_ArgTypes;
   this.FunctionName = p_FunctionName;
}
				
Public read-only properties are implemented to make these members accessible to external objects.

Next, the code implements the two extension functions that are used in this sample. These functions use the String.Substring method to extract and to return the required left-most and right-most characters.
private string left(string str, int length)
{
   return str.Substring(0, length);
}

private string right(string str, int length)
{
   return str.Substring((str.Length - length), length);
}
				
Lastly, the code implements the Invoke method that the XPath processor uses to execute an extension function:
public object Invoke(System.Xml.Xsl.XsltContext xsltContext, object[] args, System.Xml.XPath.XPathNavigator docContext)
{
   string str = null;
   if (FunctionName == "left")
      str = left(Convert.ToString(args[0]), Convert.ToInt32(args[1]));
   else if (FunctionName == "right")
      str = right(Convert.ToString(args[0]), Convert.ToInt32(args[1]));
   
   return (object) str;
}
				
This function executes the extension function whose name was specified when an object instance of this class was created in the ResolveFunction method of the custom XsltContext object. The output that the executing function generates is returned to the XPath processor.

back to the top

Code in Step 7

The XPathExtensionVariable class implements the IXsltContextVariable interface that is defined in the System.Xml.Xsl namespace.

This code uses the private member, m_VarName, to store the value of the parameter that is passed in when an object instance of this class is created in the ResolveVariable method of the custom XsltContext object. It represents the name of the user-defined variable that an object instance of this class is used to resolve. The variable name that is passed in as a parameter to the constructor is assigned to this member.
public XPathExtensionVariable(string VarName)
{
   m_VarName = VarName;
}
				
The XPath processor invokes the Evaluate method to resolve a reference to a user-defined variable. The custom XsltContext object is passed as a parameter to this method. The code in this method resolves the reference to the specified user-defined variable by accessing the XsltArgumentList property of the custom XsltContext object. The variable definitions are added to this argument list object, which is supplied as a parameter when you create an instance of the custom context object.
public object Evaluate(System.Xml.Xsl.XsltContext xsltContext)
{
   XsltArgumentList vars = ((CustomContext) xsltContext).ArgList;
   return vars.GetParam(m_VarName, null);
}
				
back to the top

Test the Sample Application

To test the XPathExtensionFunctions sample application, follow these steps:
  1. Save and then build the solution.
  2. Execute the project, and then examine the output.

    The output that is generated displays the value of each title node that the first XPath query extracts to retrieve all title nodes and the output that is generated by executing the XPath expressions that use the extension functions and the user-defined variable to extract the five left-most and right-most characters from each title.
back to the top

REFERENCES

For additional information, click the article number below to view the article in the Microsoft Knowledge Base:

313828 INFO: Roadmap for Executing XPath Queries in .NET Applications

back to the top

Modification Type:MajorLast Reviewed:10/20/2003
Keywords:kbGraphxLink kbHOWTOmaster KB324462 kbAudDeveloper