XPath 等价于 current() [英] XPath equivalent to 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 Bar
element 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);
输出
.
如果您希望在 .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 上的项目 为变量实现了 XsltContext
public 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屋!