SelectSingleNode возвращает ноль

Итак, у меня есть XML-документ, который выглядит так:

<?xml version="1.0" encoding="UTF-8"?>
<gesmes:Envelope xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01" xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref">
   <gesmes:subject>Reference rates</gesmes:subject>
   <gesmes:Sender>
       <gesmes:name>European Central Bank</gesmes:name>
   </gesmes:Sender>
   <Cube>
       <Cube time="2010-05-28">
           <Cube currency="USD" rate="1.2384"/>
           <Cube currency="JPY" rate="113.06"/>
       </Cube>
       <Cube time="2010-05-27">
           <Cube currency="USD" rate="1.2255"/>
           <Cube currency="JPY" rate="110.79"/>
       </Cube>
   </Cube>
</gesmes:Envelope>

Теперь предположим, что у меня есть XmlNode timeNode, указывающий на узел <Cube time="2010-05-28">, и document, указывающий на загруженный XML-документ. Допустим, мне нужно получить значение атрибута rate в узле <Cube currency=USD" rate="1.2384"/>, вызвав метод SelectSingleNode(string xpath).

Пока мне удалось придумать этот код:

XmlNamespaceManager nsmgr = new XmlNamespaceManager(document.NameTable);
nsmgr.AddNamespace("ecb", "http://www.ecb.int/vocabulary/2002-08-01/eurofxref");
nsmgr.AddNamespace("gesmes", "http://www.gesmes.org/xml/2002-08-01");


XmlNode currencyNode = timeNode.SelectSingleNode("descendant::ecb:Cube[@ecb:currency='USD']", nsmgr);

string rate = currencyNode.Attributes.GetNamedItem("rate").Value;

Проблема в том, что здесь currencyNode установлено значение null. Я проверил timeNode, и он указывает на правильный узел, поэтому я предполагаю, что проблема связана с путем в методе SelectSingleNode, но я не вижу, в чем проблема. Я проверил другие сообщения с похожей проблемой, но не смог найти ничего, что могло бы решить мины. Любые указатели будут оценены.


person L.E.O    schedule 01.08.2010    source источник


Ответы (2)


Атрибуты XML не имеют пространства имен по умолчанию, поэтому вам не нужно использовать для них префикс пространства имен. Попробуйте просто:

XmlNode currencyNode = timeNode.SelectSingleNode("descendant::ecb:Cube[@currency='USD']", nsmgr);

Вам также не нужно явно указывать здесь ось потомков, поскольку по умолчанию она будет смотреть на дочерние элементы, поэтому вы также можете сократить ее до:

XmlNode currencyNode = timeNode.SelectSingleNode("ecb:Cube[@currency='USD']", nsmgr);
person Quartermeister    schedule 01.08.2010
comment
Спасибо. Работал отлично. Отличный указатель на пространство имен атрибутов, я этого не знал. - person L.E.O; 01.08.2010

Измените свой xpath на

descendant::ecb:Cube[@currency="USD"]
person YoK    schedule 01.08.2010
comment
хм, к тому времени, когда я добавил свой ответ, аналогичный ответ был опубликован :(. - person YoK; 01.08.2010