有一个汇率为http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml的XML文件:
<gesmes:Envelope>
<gesmes:subject>Reference rates</gesmes:subject>
<gesmes:Sender>
<gesmes:name>European Central Bank</gesmes:name>
</gesmes:Sender>
<Cube>
<Cube time="2009-11-26">
<Cube currency="USD" rate="1.5071"/>
...
我做下一个XPath请求:
var doc = new XmlDocument();
doc.Load(url);
var node = doc.SelectSingleNode("//Cube[@currency=\"USD\""]);
var value = node.Attributes["rate"].Value;
但它会返回null
!我的错误在哪里?
如果我提出此请求,一切正常:
var node = dic.SelectSingleNode("//*[@currency=\"USD\"]");
var name = node.Name; // "Cube"
答案 0 :(得分:5)
问题是命名空间。如果您可以使用LINQ to XML,则可以非常轻松地表达此查询。否则,它有点棘手 - 你想要这样的东西:
var doc = new XmlDocument();
doc.Load(url);
XPathNavigator navigator = doc.CreateNavigator();
XmlNamespaceManager nsMgr = new XmlNamespaceManager(nav.NameTable);
nsMgr.AddNamespace("gesmes", "http://www.gesmes.org/xml/2002-08-01");
nsMgr.AddNamespace("ns0", "http://www.ecb.int/vocabulary/2002-08-01/eurofxref");
var node = doc.SelectSingleNode("//ns0:Cube[@currency=\"USD\""], nsMgr);
var value = node.Attributes["rate"].Value;
(你真的不需要需要管理器中的gesmes命名空间,但如果你需要查找任何其他元素,它会更容易。)
编辑:Peter Murray-Rust的答案在这里是一个不错的选择 - 你采取哪种方法取决于你希望元素找到的具体方式。如果您只需要一个查询的命名空间,那么将URI直接包含在XPath中是有意义的;如果您需要更多,那么您将使用命名空间管理器获得更简洁的查询。答案 1 :(得分:4)
尝试
var node = doc.SelectSingleNode("//*[local-name()='Cube' and @currency=\"USD\""]);
如果你知道的话,你可以随时添加命名空间
var node = doc.SelectSingleNode("//*[local-name()='Cube' and
namespace-uri()='http://www.ecb.int/vocabulary/2002-08-01/eurofxref' and
@currency=\"USD\""]);
虽然它很长,我更喜欢尝试整理命名空间前缀。它还避免了默认命名空间(xmlns="")
答案 2 :(得分:2)
XPathVisualizer可以派上用场。免费。它不会告诉你使用命名空间,但它会在UI中将命名空间放在你面前,它会让你很快就能测试一堆替代品。