XPath 等价于 current() [英] XPath equivalent to current()

查看:35
本文介绍了XPath 等价于 current()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何从 XPath 中引用计算 XPath 的节点?

How to reference the node on which the XPath is evaluted from within an XPath?

例如:

<Root>
    <Foo>
        <Bar><Elem>X</Elem><Ref>1</Ref></Bar>
        <Bar><Elem>Y</Elem><Ref>2</Ref></Bar>
        <Ref>2</Ref>
    </Foo>

在 Node=/Root/Foo/Ref 上执行的 XPath:

XPath executed on Node=/Root/Foo/Ref:

var myNode = GetNodeRootFooRef();
var xpath = "../Bar[Ref=.]/Elem";
myNode.SelectSingleNode(xpath); // does not work, see below

不幸的是,条件中的 . 引用了 Bar 元素,而不是我在其上执行 XPath 的原始 Ref 节点.如何从 XPath 中引用原始上下文节点?

Unfortunately the . in the conditional references the Barelement instead of the original Ref node on which I executed the XPath. How to reference the original context node from within an XPath?

推荐答案

您至少需要 XPath 2.0 才能使用单个纯 XPath 表达式解决它:for $current in .返回 ../Bar[Ref=$current]/Elem.

You need at least XPath 2.0 to solve it with a single, pure XPath expression: for $current in . return ../Bar[Ref=$current]/Elem.

Microsoft 没有 XPath 2.0 支持,但有第三方 XPath 2 实现可以插入现有的 .NET 架构并提供扩展方法,例如XmlNode(需要 using Wmhelp.XPath2; 和 NuGet 包 https://www.nuget.org/packages/XPath2/1.0.2/):

Microsoft does not have XPath 2.0 support but there are third party XPath 2 implementations that plug into the existing .NET architecture and provide extension methods on e.g. XmlNode (needs using Wmhelp.XPath2; and the NuGet package https://www.nuget.org/packages/XPath2/1.0.2/):

            string xml = @"<Root>
    <Foo>
        <Bar><Elem>X</Elem><Ref>1</Ref></Bar>
        <Bar><Elem>Y</Elem><Ref>2</Ref></Bar>
        <Ref>2</Ref>
    </Foo>
</Root>";
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(xml);

            XmlNode refEl = doc.SelectSingleNode("/Root/Foo/Ref");

            XmlNode elem = refEl.XPath2SelectSingleNode("for $current in . return ../Bar[Ref=$current]/Elem");

            Console.WriteLine(elem.OuterXml);

或者,您可以使用 XPath 3.0 或更高版本使用 let 绑定变量:let $c := 使用单个纯 XPath 表达式来实现.返回 ../Bar[Ref=$c]/Elem.

Or you can do it with XPath 3.0 or later with a single, pure XPath expression using let to bind a variable: let $c := . return ../Bar[Ref=$c]/Elem.

如果您想在 .NET 框架中的 System.Xml 上使用它,那么您可以例如安装和使用 XmlPrime,它提供了扩展方法(http://www.xmlprime.com/xmlprime/doc/4.0/using-xpath.htm#extension):>

If you want to use that on System.Xml in the .NET framework then you can for instance install and use XmlPrime, it offers extension methods (http://www.xmlprime.com/xmlprime/doc/4.0/using-xpath.htm#extension):

            string xml = @"<Root>
    <Foo>
        <Bar><Elem>X</Elem><Ref>1</Ref></Bar>
        <Bar><Elem>Y</Elem><Ref>2</Ref></Bar>
        <Ref>2</Ref>
    </Foo>
</Root>";
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(xml);

            XmlNode refEl = doc.SelectSingleNode("/Root/Foo/Ref");

            XmlNode elem = refEl.XPathSelectSingleNode("let $c := . return ../Bar[Ref=$c]/Elem");

            Console.WriteLine(elem.OuterXml);

输出Y.

如果您希望在 .NET 框架 XPath API 中具有可变分辨率,则 SelectSingleNode/SelectNodes 的第二个参数是 XmlNamespaceManager,它是 XsltContext 有一个方法 ResolveVariable https://msdn.microsoft.com/en-us/library/system.xml.xsl.xsltcontext.resolvevariable(v=vs.110).aspx.有 Codeplex 上的项目 为变量实现了 XsltContextpublic class DynamicContext : XsltContext 中的解析,所以你可以使用它:

If you want to have variable resolution within the .NET framework XPath APIs then the second argument to SelectSingleNode/SelectNodes is an XmlNamespaceManager which is a base class of XsltContext which has a method ResolveVariable https://msdn.microsoft.com/en-us/library/system.xml.xsl.xsltcontext.resolvevariable(v=vs.110).aspx. There is project on Codeplex that implements that XsltContext for variable resolution in the public class DynamicContext : XsltContext so you could use that:

            XmlDocument doc = new XmlDocument();
            doc.LoadXml(@"<Root>
    <Foo>
        <Bar><Elem>X</Elem><Ref>1</Ref></Bar>
        <Bar><Elem>Y</Elem><Ref>2</Ref></Bar>
        <Ref>2</Ref>
    </Foo>
</Root>");

            XmlNode refEl = doc.SelectSingleNode("Root/Foo/Ref");

            DynamicContext context = new DynamicContext();
            context.AddVariable("current", refEl);

            XmlNode elem = refEl.SelectSingleNode("../Bar[Ref = $current]/Elem", context);

            Console.WriteLine(elem.OuterXml);

请参阅 https://weblogs.asp.net/cazzu/30888 中的文档.

这篇关于XPath 等价于 current()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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