使用ms:XPathExpression中的xpath函数 [英] Using ms: xpath functions inside XPathExpression

查看:70
本文介绍了使用ms:XPathExpression中的xpath函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆