使用ms:XPathExpression中的xpath函数 [英] Using ms: xpath functions inside XPathExpression
问题描述
我正在尝试使用Microsoft XPath扩展功能(例如ms:string-compare
I am trying to use Microsoft XPath Extension Functions (such as ms:string-compare http://msdn.microsoft.com/en-us/library/ms256114.aspx) inside an XPathExpression object.
这些函数是MSXML库内部的扩展,如果我在XslCompiledTransform中使用它们(简单地添加"ms"命名空间),它们的工作就像一个魅力:
These functions are extensions inside the MSXML library, and if I use them in an XslCompiledTransform (simply adding the "ms" namespace) they work like a charm:
var xsl =
@"
<?xml version=""1.0"" encoding=""UTF-8""?>
<xsl:stylesheet version=""2.0"" xmlns:xsl=""http://www.w3.org/1999/XSL/Transform""
xmlns:xs=""http://www.w3.org/2001/XMLSchema""
xmlns:fn=""http://www.w3.org/2005/xpath-functions""
xmlns:ms=""urn:schemas-microsoft-com:xslt"">
<xsl:output method=""xml"" version=""1.0"" encoding=""UTF-8"" indent=""yes""/>
<xsl:template match=""/Data"">
<xsl:element name=""Result"">
<xsl:value-of select=""ms:string-compare(@timeout1, @timeout2)""/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>";
var xslDocument = new XmlDocument();
xslDocument.LoadXml(xsl);
var transform = new XslCompiledTransform();
transform.Load(xslDocument);
然后我尝试在XPathExpression中使用它们:
Then I tried using them in an XPathExpression:
XPathNavigator nav = document.DocumentElement.CreateNavigator();
XPathExpression expr = nav.Compile("ms:string-compare(/Data/@timeout1, /Data/@timeout2)");
XmlNamespaceManager manager = new XmlNamespaceManager(document.NameTable);
manager.AddNamespace("ms", "urn:schemas-microsoft-com:xslt");
expr.SetContext(manager);
nav.Evaluate(expr);
但是我得到一个异常由于功能未知,此查询需要XsltContext".
But I get an exception "XsltContext is needed for this query because of an unknown function".
XsltContext是特定的XmlNamespaceManager,但我不知道是否可以在没有实际XslCompiledTransform(它是抽象的)的情况下实例化它并将其用作我的表达上下文.
XsltContext is a specific XmlNamespaceManager, but I don't know if it's possible to instantiate it without an actual XslCompiledTransform (it's abstract) and use it as my expression context.
是否有任何方法(或使用XPathExpression内部使用ms:扩展的其他方法)?
Is there any way to do this (or any other way to use ms: extensions inside an XPathExpression)?
推荐答案
.net框架dom类中不包含这些ms前缀的函数.您需要创建自定义函数才能执行相同的操作.
These ms prefixed functions are not included in .net framework dom classes. you need to create your custom functions to do same thing.
您可以在下面使用示例代码;
you may use sample code below;
string xpath = "my:string-compare('1','1)";
System.Xml.XmlNamespaceManager nsManager = new XsltContext();
nav.Select(xpath, nsManager );
或
XPathExpression compiledXPath = XPathExpression.Compile(xpath);
compiledXPath.SetContext(nsManager);
nav.Evaluate(compiledXPath);
您将需要这些课程;
public class XsltContext : System.Xml.Xsl.XsltContext
{
public XsltContext()
{
Initialize();
}
public XsltContext(System.Xml.NameTable nameTable)
: base(nameTable)
{
Initialize();
}
private void Initialize()
{
RegisterFunction("my", "string-compare", typeof(StringCompare));
}
public override string LookupNamespace(string prefix)
{
return base.LookupNamespace(prefix);
}
public override int CompareDocument(string baseUri, string nextbaseUri)
{
return string.CompareOrdinal(baseUri, nextbaseUri);
}
public override bool PreserveWhitespace(System.Xml.XPath.XPathNavigator node)
{
return false;
}
public void RegisterFunction(string prefix, string name, Type function)
{
if (function == null)
throw new ArgumentNullException("function");
if (name == null)
throw new ArgumentNullException("name");
functions[prefix + ":" + name] = function;
}
Dictionary<string, Type> functions = new Dictionary<string, Type>();
public override System.Xml.Xsl.IXsltContextFunction ResolveFunction(string prefix, string name, System.Xml.XPath.XPathResultType[] argTypes)
{
Type functionType = null;
if (functions.TryGetValue(prefix + ":" + name, out functionType))
{
System.Xml.Xsl.IXsltContextFunction function = Activator.CreateInstance(functionType) as System.Xml.Xsl.IXsltContextFunction;
return function;
}
return null;
}
public override System.Xml.Xsl.IXsltContextVariable ResolveVariable(string prefix, string name)
{
return null;
}
public override bool Whitespace
{
get
{
return false;
}
}
internal static string GetValue(object v)
{
if (v == null)
return null;
if (v is System.Xml.XPath.XPathNodeIterator)
{
foreach (System.Xml.XPath.XPathNavigator n in v as System.Xml.XPath.XPathNodeIterator)
return n.Value;
}
return Convert.ToString(v);
}
}
class StringCompare : System.Xml.Xsl.IXsltContextFunction
{
public System.Xml.XPath.XPathResultType[] ArgTypes
{
get
{
return new System.Xml.XPath.XPathResultType[]
{
System.Xml.XPath.XPathResultType.String,
System.Xml.XPath.XPathResultType.String,
System.Xml.XPath.XPathResultType.String
};
}
}
public object Invoke(System.Xml.Xsl.XsltContext xsltContext, object[] args, System.Xml.XPath.XPathNavigator docContext)
{
string arg1 = XsltContext.GetValue(args[0]);
string arg2 = XsltContext.GetValue(args[1]);
string locale = "en-US";
if (args.Length > 2)
locale = XsltContext.GetValue(args[2]);
System.Globalization.CultureInfo culture = System.Globalization.CultureInfo.GetCultureInfo(locale);
return string.Compare(arg1, arg2, false, culture);
}
public int Maxargs
{
get
{
return 3;
}
}
public int Minargs
{
get
{
return 2;
}
}
public System.Xml.XPath.XPathResultType ReturnType
{
get
{
return System.Xml.XPath.XPathResultType.Number;
}
}
}
这篇关于使用ms:XPathExpression中的xpath函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!