为什么我对Web上的XML文件的XPath请求不起作用?

时间:2009-11-26 19:21:54

标签: c# .net xml web-services xpath

有一个汇率为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"

3 个答案:

答案 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中将命名空间放在你面前,它会让你很快就能测试一堆替代品。

alt text