为XPath自定义函数(因为XPath1.0的函数非常有限)[附源代码下载]
想要一个正则表达式的匹配函数,但是XPath1.0中间没有,
只好自己扩展一个,在网上搜了一下,有一篇文章不错,
http://www.microsoft.com/china/MSDN/library/data/xml/AddingCustomFunctionstoXpath.mspx?mfr=true
该文章定义了一个split,一个replace,不过就是没有match,
只好在它的基础上,扩展一下
仔细观察一下代码,发现想要扩展一个函数很简单,只要修改这几段就好了:
1:CustomContext.cs
// 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 "Match":
// Usage
// myFunctions:Matches(string source, string Regex_pattern) returns Boolean
func = new XPathRegExExtensionFunction("Match", 2, 2, new
XPathResultType[] {XPathResultType.String, XPathResultType.String}
, XPathResultType.Boolean );
break;
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;
}
public override IXsltContextFunction ResolveFunction(string prefix,
string name, XPathResultType[] ArgTypes)
{
XPathRegExExtensionFunction func = null;
// Create an instance of appropriate extension function class.
switch (name)
{
case "Match":
// Usage
// myFunctions:Matches(string source, string Regex_pattern) returns Boolean
func = new XPathRegExExtensionFunction("Match", 2, 2, new
XPathResultType[] {XPathResultType.String, XPathResultType.String}
, XPathResultType.Boolean );
break;
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;
}
2: XPathRegExExtensionFunction.cs
// This method is invoked at run time to 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 "Match":
r = new Regex(args[1].ToString());
MatchCollection m = r.Matches(args[0].ToString());
if (m.Count == 0)
{
return false;
}
else
{
return true;
}
break;
case "Split":
r = new Regex(args[1].ToString());
string[] s1 = r.Split(args[0].ToString());
int n = Convert.ToInt32(args[2]);
if (s1.Length < n)
str = "";
else
str = s1[n - 1];
break;
case "Replace":
r = new Regex(args[1].ToString());
string s2 = r.Replace(args[0].ToString(), args[2].ToString());
str = s2;
break;
}
return (object)str;
}
public object Invoke(XsltContext xsltContext, object[] args,
XPathNavigator docContext)
{
Regex r;
string str = null;
// The two custom XPath extension functions
switch (m_FunctionName)
{
case "Match":
r = new Regex(args[1].ToString());
MatchCollection m = r.Matches(args[0].ToString());
if (m.Count == 0)
{
return false;
}
else
{
return true;
}
break;
case "Split":
r = new Regex(args[1].ToString());
string[] s1 = r.Split(args[0].ToString());
int n = Convert.ToInt32(args[2]);
if (s1.Length < n)
str = "";
else
str = s1[n - 1];
break;
case "Replace":
r = new Regex(args[1].ToString());
string s2 = r.Replace(args[0].ToString(), args[2].ToString());
str = s2;
break;
}
return (object)str;
}
另外一个文件XPathExtensionVariable.cs其实和函数扩展没有太多的关系,那是设置参数的。
这连个文件修改好了之后,就可以调用了:
query = navigator.Compile("xdUtil:Match(9,'\\d')");
CustomContext cntxt = new CustomContext();
// Add a namespace definition for myFunctions prefix.
cntxt.AddNamespace("xdUtil", "http://myXPathExtensionFunctions");
query.SetContext(cntxt);
Evaluate(query, navigator);
CustomContext cntxt = new CustomContext();
// Add a namespace definition for myFunctions prefix.
cntxt.AddNamespace("xdUtil", "http://myXPathExtensionFunctions");
query.SetContext(cntxt);
Evaluate(query, navigator);
当然,要是支持XPath2.0 就好了,XPath2.0这些函数都是内置支持的,可惜目前好像还不支持。
全部的代码在这里:
/Files/cleo/XPathExtFunction.rar
posted on 2006-04-03 17:37 无为而为-凡事从积极的态度做起 阅读(717) 评论(0) 编辑 收藏 举报