Summary: Prajakta Joshi discusses how to create custom functions for XPath using the System.xml API in the .NET Framework SDK. The subject involves adding extended functions to XPath 1.0, looking forward to XPath 2.0 and extension functions in XSLT. (Page Page Page) In XML and XSL public newsgroups, requests for extended functions are a topic discussed. The motivation to write this article is because I noticed that there is a lot of user posts involving this topic. Xpath 1.0's XPath expression can return one of the following four basic XPath data types: * String * Numeric * Boolean * Node Set XSLT variable introduces an additional type in the expression language - Result Tree Fragment (Results) ). The core function library in XPath provides several basic tools for operating the XPath data type. Throughout these functions, you will find that this is not a comprehensive collection that meets all users. XPath type Function Node Set Last (), Position (), Count (), ID (), Local-name (), Namespace-Uri (), Name () String String (), Concat (), Starts-with ( ), Contains () Substring-Before () Substring -After (), Substring () String-length (), Normalize-Space () , False (), LANG () NuMBer (), SUM (), Floor (), CEILING (), Round (), CEILT 1.0 (), Key (), Format-Number (), CURRENT (), Unparsed-entity-uri (), generate-id (), system-protety () requires non-XPath data types (for example, date) or XML development with powerful / custom data operation with XPath data type Personnel usually require additional functions. This article is intended to overview How to use System.xml in the Microsoft .NET Framework SDK to implement custom functions for XPath. Two strings are comparison when writing my first XPath query, I need to perform a comparison of uncomment to both strings.
The books.xml I have written as follows:
I solved this problem using the XPath class in system.xml.xpath namespace by the following code snippet: use system; use system.xml; use system.xml.xpath; public class sample {public static void main (String [] args .) {// Load source XML into XPathDocument XPathDocument xd = new XPathDocument (args [0], XmlSpace.Preserve);. // Create XPathNavigator from XPathDocument XPathNavigator nav = xd.CreateNavigator (); XPathExpression expr; expr = nav.Compile ( "/bookstore/book/title[translate(.,'abcdefghijklmnopqrstuvwxyz ',' ABCDEFGHIJKLMNOPQRSTUVWXYZ ') =' HARRY POTTER AND THE GOBLET OF FIRE ']"); XPathNodeIterator iterator = nav.Select (expr); // Iterate through selected Nodes. While ("Book Title: {0}", Iterator.current.Value);}}} This code generates the following output: Book Title: Harry Potter and the GOBLET OF Fire Although this solution is a bit long, I still solve my problem. When writing XPath queries for a few days, I want to remove string into an array of sub-strings in locations that match the definition of regular expressions. XML Version = "1.0" Encoding = "UTF-8"?>
The figure below explains the role of the xsltcontext class, the IxSltconTextFunction interface, and the IXSLTCONTEXTVARIA interface in my solution. Figure 1. Key Steps in the Role Solution of XSLTCONText 1.xPatHexPression.SetContext (CustomContext) provides an XPath processor (XPathnavigator), which has custom contexts for parsing user-defined functions and variables. CustomContext implements two key ways: resolvefunction () and resolvevariable () and resolvevariable (). 2. When Xpathnavigator encounters user-defined functions in the XPATHEXPRESSION, it is called the resolvefunction () method for custom context. ResolveFunction () Returns the appropriate custom function derived from IXSLTCONTextFunction. 3.XPathnavigator Call the invoke () method for this custom function at runtime. 4. When Xpathnavigator detects user-defined variables in XPATHEXPRESSION, it is called the resolvevariable () method for custom context. Resolvevariable () Returns the appropriate custom variable derived from IXSLTCONTEXTVARIABLE. 5. Xpathnavigator calls the evAate () method for this custom variable at runtime. I decided to write a custom XPath function-split () so that the function of the function is similar to the regex.split () method in the .NET SDK. Here is how to combine all of these code snippets. The role of the XSLTContext class first, I implemented my custom xsltContext to provide the XPath processor to provide information on resolving user-defined functions. ResolveFunction and ResolveVariable are two key ways to the XSLTContext class, and users must override them to implement custom parsing. These methods are called by XPathnavigator during runtime to resolve references to user-defined functions and variables in XPath query expressions. Note that I encapsulated a resolvevariable object in the CustomContext class. This object is a container for variables in the XPath expression.
public class CustomContext: XsltContext {// XsltArgumentList to store my user defined variables private XsltArgumentList m_ArgList; // Constructors public CustomContext () {} public CustomContext (NameTable nt): base (nt) {} public CustomContext (NameTable nt, XsltArgumentList argList) :.. base (nt) {m_ArgList = argList;} // Returns the XsltArgumentList that contains custom variable definitions public XsltArgumentList argList {get {return m_ArgList;}} // Function to resolve references to my custom functions public override IXsltContextFunction ResolveFunction (string prefix, string name, XPathResultType [] argTypes) {XPathRegExExtensionFunction func = null; // Create an instance of appropriate extension function class switch (name) {case "Split":. // Usage // myFunctions: Split (string source, string Regex_pattern, Int n) returns string func = new XPathRegExExtensionFunction ( "Split", 3, 3, new XPathResultType [] {XPathResultType.String, XPathResultType.String, XPathResultType.Number}, XPathResultType.String); break; case "Replace": // Usage // myFunctions: Replace (string source, string Regex_pattern, string replacement_string) returns string func = new XPathRegExExtensionFunction ( "Replace", 3, 3, new XPathResultType [] {XPathResultType.String, XPathResultType.String, XPathResultType.String}, XPathResultType.String); break Return Func;
} // Function to resolve references to my custom variables public override IXsltContextVariable ResolveVariable (string prefix, string name) {// Create an instance of an XPathExtensionVariable XPathExtensionVariable Var;.. Var = new XPathExtensionVariable (name); return Var;} public override int CompareDocument (string baseUri, string nextbaseUri) {return 0;} public override bool PreserveWhitespace (XPathNavigator node) {return true;} public override bool Whitespace {get {return true;}}} IXsltContextFunction the next step is to achieve the role of interfaces for CustomContext The IXSLTCONTEXTFUNCTION interface used by the class. The invoke () method of this object is called by the XPathnavigator using the provided parameters at runtime.
public class XPathRegExExtensionFunction: IXsltContextFunction {private XPathResultType [] m_ArgTypes; private XPathResultType m_ReturnType; private string m_FunctionName; private int m_MinArgs; private int m_MaxArgs; // Methods to access the private fields public int Minargs {get {return m_MinArgs;}} public int. maxargs {get {return m_MaxArgs;}} public XPathResultType [] argTypes {get {return m_ArgTypes;}} public XPathResultType ReturnType {get {return m_ReturnType;}} // Constructor public XPathRegExExtensionFunction (string name, int minArgs, int maxArgs, XPathResultType [ ] argTypes, XPathResultType returnType) {m_FunctionName = name; m_MinArgs = minArgs; m_MaxArgs = maxArgs; m_ArgTypes = argTypes; m_ReturnType = returnType;} // This method is invoked at run time t o execute the user defined function public object Invoke (XsltContext xsltContext, object [] args, XPathNavigator docContext) {Regex r; string str = null; // The two custom XPath extension functions switch (m_FunctionName) {case "Split":. r = New regex (args [1] .tostring ()); string [] s1 = r.Split (args [0] .tostring ()); int n = convert.toint32 (args [2]); if (S1. Length R.Replace (Args [0] .tostring (), args [2] .tostring ()); str = s2; break;}}}}}}}}}}}}} The role XPath expression of the IXSLTCONTEXTVARIABLE interface can contain user-defined Variables reference, for example: xpatHexpression expr1 = nav.compile ("MyFunctions: split (string (.), ',', $ Var)"); I need to implement the IXSLTCONTEXTVARIABLE interface and override the evAlate () method (this method is running when public class XPathExtensionVariable: IXsltContextVariable {// The name of the user-defined variable to resolve private string m_VarName; public XPathExtensionVariable (string VarName) {m_VarName = VarName;} // This method is invoked at run time to find the value of the user defined variable public object Evaluate (XsltContext xsltContext) {XsltArgumentList vars = ((CustomContext) xsltContext) .ArgList; return vars.GetParam (m_VarName, null);}. public bool isLocal {get {return false;}} public bool IsParam { Get {returnaf false; }}} Public xpathResultType VariableType {get {return xpathresulttype.Any;}}} Merge code together, I use the XPATHEXPRESSION.SETCONTEXT () method to incorporate it into my custom context object. Figure 1 summarizes all the steps in the solution. Note that the XSLTContext class is inherited from XMLNameSpaceManager and adds my custom namespace by using AddNameSpace () to the collection. using System; using System.Xml; using System.Xml.Xsl; using System.Xml.XPath; using System.Text.RegularExpressions; public class sample {public static void Main (string [] argc) {// Load source XML into . XPathDocument XPathDocument doc = new XPathDocument ( "books.xml", XmlSpace.Preserve); // Create XPathNavigator from XPathDocument XPathNavigator nav = doc.CreateNavigator ();.. // Add user-defined variable to the XsltArgumentList XsltArgumentList varList = new XsltArgumentList (); varList.AddParam ( "var", "", 2);.. // Compile the XPathExpression // Note that the compilation step only checks the query expression // for correct XPath syntax // User defined functions and variables are not resolved XPathExpression expr1 = nav.Compile. ( "myFunctions:. Split (string (), ',', $ var)"); // Create an instance of a custom XsltContext object CustomContext cntxt = new CustomContext (new NameTable. (), VARLIST); // . Add a namespace definition for myFunctions prefix cntxt.AddNamespace ( "myFunctions", "http: // myXPathExtensionFunctions"); // Associate the custom context with the XPathExpression object expr1.SetContext (cntxt); XPathNodeIterator it = nav.Select (. "/ Books / book / authors"); while (it.movenext ()) {console.writeline ("authors: {0}", it.current.value; console.writeline ("Second Author: {0}" IT.CURRENT.EVALUATE (EXPR1));}}} Run this code will generate the following output: