您至少需要XPath 2.0才能使用單個純XPath表達式來解決此問題:for $current in . return ../Bar[Ref=$current]/Elem
。
Microsoft不支持XPath 2.0,但有第三方XPath 2實現插入到現有的.NET體系結構中,並在例如Web服務器上提供擴展方法。 XmlNode
(需要using Wmhelp.XPath2;
和NuGet包https://www.nuget.org/packages/XPath2/1.0.2/):let $c := . return ../Bar[Ref=$c]/Elem
:
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
到可變結合單一,純XPath表達式做到這一點。
如果你想使用上的System.Xml在.NET框架,那麼你可以例如安裝和使用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。
你需要輸出什麼? –