2013-06-18 2 views
13

Я пытаюсь читать XML из потока чтения, а также получаю ответ XML. Но когда я пытаюсь прочитать его узлы, он всегда возвращает null.XML-документ SelectSingleNode возвращает null

var request = (HttpWebRequest) WebRequest.Create(address); 
var response = (HttpWebResponse) request.GetResponse(); 
var stream = response.GetResponseStream(); 

if(stream != null) 
{ 
    var xmlReader = new XmlTextReader(stream); 
    var xmlDocument = new XmlDocument(); 
    xmlDocument.Load(xmlReader); 
    var node = xmlDocument.SelectSingleNode("RateQuote"); 
} 

XML Document

<RateQuoteResponse xmlns="http://ratequote.usfnet.usfc.com/v2/x1"> 
    <STATUS> 
    <CODE>0</CODE> 
    <VIEW>SECURED</VIEW> 
    <VERSION>...</VERSION> 
    </STATUS> 
<RateQuote> 
    <ORIGIN> 
    <NAME>KNOXVILLE</NAME> 
    <CARRIER>USF Holland, Inc</CARRIER> 
    <ADDRESS>5409 N NATIONAL DR</ADDRESS> 
    <CITY>KNOXVILLE</CITY> 
    <STATE>TN</STATE> 
    <ZIP>37914</ZIP> 
    <PHONE>8664655263</PHONE> 
    <PHONE_TOLLFREE>8006545963</PHONE_TOLLFREE> 
    <FAX>8656379999</FAX> 
    </ORIGIN> 
    <DESTINATION> 
    <NAME>KNOXVILLE</NAME> 
    <CARRIER>USF Holland, Inc</CARRIER> 
    <ADDRESS>5409 N NATIONAL DR</ADDRESS> 
    <CITY>KNOXVILLE</CITY> 
    <STATE>TN</STATE> 
    <ZIP>37914</ZIP> 
    <PHONE>8664655263</PHONE> 
    <PHONE_TOLLFREE>8006545963</PHONE_TOLLFREE> 
    <FAX>8656379999</FAX> 
    </DESTINATION> 
    <ORIGIN_ZIP>37914</ORIGIN_ZIP> 
    <DESTINATION_ZIP>37909</DESTINATION_ZIP> 
    <TOTAL_COST>99.24</TOTAL_COST> 
    <SERVICEDAYS>1</SERVICEDAYS> 
    <INDUSTRYDAYS>1.6</INDUSTRYDAYS> 
    <CLASSWEIGHT> 
     <CLASS>55</CLASS> 
     <ASCLASS>50</ASCLASS> 
     <WEIGHT>100</WEIGHT> 
     <CHARGES>0.0</CHARGES> 
    </CLASSWEIGHT> 
</RateQuote> 
</RateQuoteResponse> 

ответ

26

XML-документ использует пространство имен по умолчанию "http://ratequote.usfnet.usfc.com/v2/x1". Вам нужно изменить вызов SelectSingleNode, чтобы использовать это пространство имен.

Вам необходимо настроить диспетчер namspace, а затем отправить его на SelectSingleNode.

var nsmgr = new XmlNamespaceManager(doc.NameTable); 
nsmgr.AddNamespace("rate", "http://ratequote.usfnet.usfc.com/v2/x1"); 
var node = xmlDocument.SelectSingleNode("//rate:RateQuote", nsmgr); 

EDIT RateQuoteResponse элемент имеет пространство имен по умолчанию xmlns="...". Это означает, что все элементы также используют это пространство имен, если только это не переопределено.

+1

Спасибо за пример ... –

+0

'var node = xmlDocument.SelectSingleNode (" // rate: RateQuote/TOTAL_COST ", nsmgr);' Почему это не работает? Он снова бросает «null» –

+2

@SSS: У вас опять та же проблема: элемент 'TOTAL_COST' также находится в этом пространстве имен. (Я редактирую свой ответ, чтобы упомянуть об этом.) –

6

Проблема заключается в том, что вы просите для RateQuote элемента без имен - тогда как RateQuote элемент фактически в пространстве имен с URI http://ratequote.usfnet.usfc.com/v2/x1.

Вы можете либо использовать XmlNamespaceManager для решения пространства имен в вашем XPath, или использовать LINQ к XML, который имеет очень простое управление пространства имен:

var document = XDocument.Load(stream); 
XNamespace ns = "http://ratequote.usfnet.usfc.com/v2/x1"; 
XElement rateQuote = document.Root.Element(ns + "RateQuote"); 

Лично я хотел бы использовать LINQ для XML, если это возможно - Мне гораздо удобнее пользоваться, чем XmlDocument. Вы все равно можете использовать XPath, если хотите, но я лично предпочитаю использовать методы запросов.

РЕДАКТИРОВАТЬ: Обратите внимание, что пространство имен по умолчанию применяется также к дочерним элементам. Таким образом, чтобы найти TOTAL_COST элемент вам нужно:

XElement cost = document.Root 
         .Element(ns + "RateQuote") 
         .Element(ns + "TOTAL_COST"); 
+0

Спасибо, Можете ли вы отправить пример кода LINK, чтобы выбрать узел« RateQuote'? –

+0

@SSS: Это код, который я * написал * - переменная 'rateQuote' относится к элементу' '. –

+0

ok thankyou .... –

5

Вы можете удалить пространство имен при чтении файла, просто отключить пространства имен на XmlTextReader:

var request = (HttpWebRequest) WebRequest.Create(address); 
var response = (HttpWebResponse) request.GetResponse(); 
var stream = response.GetResponseStream(); 

if(stream != null) 
{ 
    var xmlReader = new XmlTextReader(stream); 
    xmlReader.Namespaces = false; 
    var xmlDocument = new XmlDocument(); 
    xmlDocument.Load(xmlReader); 
    var node = xmlDocument.SelectSingleNode("RateQuote"); 
} 

После этого у вас нет заботиться о пространстве имен при использовании XPath/LINQ для ваших XML-элементов.

+0

pfff! Большое спасибо! Я потратил 3 часа на различные решения, чтобы наконец понять, что пространство имен разрушает все чтение документа ... – Cowwando

1

Вы также должны быть в состоянии сделать:

... 
var node = xmlDocument["RateQuote"]; 
... 

Синтаксис VB для этого есть:

... 
Dim node as XmlNode = xmlDocument("RateQuote") 
... 
5

Изменение:

var xmlReader = new XmlTextReader(stream); 
var xmlDocument = new XmlDocument(); 
xmlDocument.Load(xmlReader); 

в

var xmlReader = new XmlTextReader(stream) { Namespaces = false }; 
var xmlDocument = new XmlDocument(); 
xmlDocument.Load(xmlReader); 

Но ...Вы можете также улучшить код немного, и использовать что-то вроде этого:

var xmlDocument = new XmlDocument(); 
xmlDocument.Load(new XmlTextReader(stream) { Namespaces = false }); 

А если вы предпочитаете загружать из строки данных XML, вы можете использовать:

var xmlDocument = new XmlDocument(); 
xmlDocument.Load(new XmlTextReader(new StringReader(data)) { Namespaces = false }); 

С такими изменениями, быть в состоянии получить нужный узел с помощью SelectSingleNode без использования пространств имен.

Смежные вопросы