2008年6月5日

[.Net] SelectNodes case insensitively with .Net Xml DOM

The Microsoft .Net Framework provides interfaces that you can use them to implement your own extended functions to work in XPath expressions, and here are what you ought to know when you want to perform a case-insensitive search.

First is to write your own XslContext class, to do  this, create a class inherits from System.Xml.Xsl.XslContext class, and implement its abstract methods.

public class XmlExtendedContext:XsltContext
{
public override IXsltContextFunction ResolveFunction
(string prefix,
string name,
XPathResultType[] ArgTypes)
{
IXsltContextFunction resolvedFunction = null;
if (this.LookupNamespace(prefix) == EqualsFunction.Namespace &&
name == EqualsFunction.FunctionName)
resolvedFunction = new EqualsFunction();
return resolvedFunction;
}
}


The ResolveFunction() method resolves custom functions in XPath. So we have to write another class EqualsFunction to actually perform the function.





public class EqualsFunction{
public const string Namespace =
"http://myextensions.xml";
public const string FunctionName
= "equals";

private XPathResultType[] m_argTypes =
new XPathResultType[] {
XPathResultType.Any,
XPathResultType.Any };

#region IXsltContextFunction Members
public XPathResultType[] ArgTypes
{get{return m_argTypes;}}
private string GetArgs(object arg)
{
string stringValue;
if (arg is string)
stringValue = (string)(arg);
else if (arg is XPathNodeIterator)
{
XPathNodeIterator i =
(XPathNodeIterator)arg;
if (i.MoveNext() == true)
{
XPathNavigator navigator = i.Current;
stringValue = navigator.ToString();
}
else
throw new ArgumentNullException();
}
else
throw new ArgumentNullException();
return stringValue;
}
public object Invoke(
XsltContext xsltContext,
object[] args,
XPathNavigator docContext)
{
if (args.Length != 2)
throw new ArgumentNullException();
string argument1 = GetArgs(args[0]);
string argument2 = GetArgs(args[1]);
bool result = string.Equals( argument1, argument2, StringComparison.CurrentCultureIgnoreCase);
return result;
}
#endregion
}



And to use newly created function in your code:



//Create custom Context
XmlExtendedContext ctx = new XmlExtendedContext(doc.NameTable);

//Prepare namespace manager
ctx.AddNamespace("s", XmlExtendedContext.EqualsFunction.Namespace);

//perform the search
return doc.SelectSingleNode"//*/child[s:equals(@Name,\"TEST\")]",ctx);













沒有留言:

Blog Archive

About Me