如何引用从 XPath 中评估 XPath 的节点?
例如。:
<Root>
<Foo>
<Bar><Elem>X</Elem><Ref>1</Ref></Bar>
<Bar><Elem>Y</Elem><Ref>2</Ref></Bar>
<Ref>2</Ref>
</Foo>
在节点上执行的 XPath=
/Root/Foo/Ref
:var myNode = GetNodeRootFooRef();
var xpath = "../Bar[Ref=.]/Elem";
myNode.SelectSingleNode(xpath); // does not work, see below
不幸的是
.
在条件引用中 Bar
元素而不是原来的 Ref
我在其上执行 XPath 的节点。如何从 XPath 中引用原始上下文节点?
最佳答案
您至少需要 XPath 2.0 才能使用单个纯 XPath 表达式来解决它: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/ ):
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 或更高版本,使用单个纯 XPath 表达式,使用
let
绑定(bind)变量:let $c := . return ../Bar[Ref=$c]/Elem
.如果您想在 .NET 框架中的 System.Xml 上使用它,那么您可以安装和使用 XmlPrime,它提供了扩展方法 (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);
输出
<Elem>Y</Elem>
.如果您想在 .NET 框架 XPath API 中获得可变分辨率,那么
SelectSingleNode/SelectNodes
的第二个参数是 XmlNamespaceManager
它是 XsltContext
的基类它有一个方法 ResolveVariable
https://msdn.microsoft.com/en-us/library/system.xml.xsl.xsltcontext.resolvevariable(v=vs.110).aspx .有project on Codeplex实现 XsltContext
public class DynamicContext : XsltContext
中的可变分辨率所以你可以使用它: 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 中的文档.
关于xml - XPath 等效于 current(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42032599/