Che cosa è un buon modo per trovare un valore specifico in un documento XML utilizzando C #?

StackOverflow https://stackoverflow.com/questions/374734

  •  22-08-2019
  •  | 
  •  

Domanda

sto chiamando un webservice esposto da Oracle che accetta un ingresso di un ItemID e ritorna a me corrispondente numero di articolo. Voglio afferrare il Numero oggetto che è stato restituito dal XML contenuta nella risposta.

L'XML è simile al seguente:

<env:Envelope
  xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:ns0="http://dev1/MyWebService1.wsdl">
 <env:Header>
  <wsse:Security
    xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
    xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
    xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
    env:mustUnderstand="1"/>
 </env:Header>
 <env:Body>
  <ns0:getItemNbrByItemIdResponseElement>
   <ns0:result>1010603</ns0:result>
  </ns0:getItemNbrByItemIdResponseElement>
 </env:Body>
</env:Envelope>

Sono interessato a catturare solo la <ns0:result>1010603</ns0:result> particolare solo il 1.010.603.

Non ho fatto un sacco di lavoro XML parsing utilizzando C # e sto giocando con alcuni metodi differenti finora. Qual è il metodo consigliato per fare questo?

Sono in VS2008 (così XPath è disponibile, ecc.)

È stato utile?

Soluzione

userei personalmente LINQ to XML, perché trovo che più facile da trattare con rispetto XPath, in particolare quando sono coinvolti gli spazi dei nomi. Faresti fare qualcosa di simile:

XNamespace ns0 = "http://dev1/MyWebService1.wsdl";

String result = doc.Descendants(ns0 + "result").First().Value;

Si noti che doc qui si pensa che sia un XDocument , non XmlDocument . (La mia ipotesi è che questo è il motivo per cui non è stato mostrato per voi.)

Altri suggerimenti

FWIW si può imbrogliare il problema dello spazio dei nomi con un XPath in questo modo: //*[local-name()='result']

Se non si vuole andare per Linq si potrebbe usare XPathDocument per recuperare il valore:

XPathDocument xmldoc = new XPathDocument(@"C:\tmp\sample.xml");
XPathNavigator nav = xmldoc.CreateNavigator();

XmlNamespaceManager nsMgr = new XmlNamespaceManager(nav.NameTable);
nsMgr.AddNamespace("ns0", "http://dev1/MyWebService1.wsdl");

XPathNavigator result = nav.SelectSingleNode("//ns0:result", nsMgr);
System.Diagnostics.Debug.WriteLine(result.Value);

XPathDocument ha un ingombro di memoria inferiore ed è più probabile più veloce nello scenario di XmlDocument. XmlDocument costruisce un modello di oggetto completa del documento XML in memoria, mentre XPathDocument non farlo.

Al largo della parte superiore della mia testa, il seguente dovrebbe funzionare:

XmlDocument doc = new XmlDocument();
doc.PreserveWhitespace = true;

XmlNamespaceManager mgr = GetNamespace(doc);
doc.LoadXml(xmltext);

XmlNode nd = doc.DocumentElement.SelectSingleNode("//ns0:result", mgr);

Il codice namespace è simile al seguente:

private XmlNamespaceManager GetNamespace(XmlDocument document)
{
    XmlNamespaceManager mgr = new XmlNamespaceManager(document.NameTable);
    mgr.AddNamespace("ns0", "http://dev1/MyWebService1.wsdl");
    return mgr;
}

È necessario utilizzare il gestore namespace perché il documento XML ha spazi dei nomi ad esso associati, e XPath utilizza questo nella risoluzione query.

Per risolvere questo problema, ho usato la risposta di Jon Skeet. Ecco il codice che ho dovuto implementare per fare questo lavoro (per chiunque altro beneficio futuro).

XmlDocument xmlDoc = new XmlDocument();

XNamespace ns0 = "http://dev1/MyWebService1.wsdl";

xmlDoc.Load(request.GetResponse().GetResponseStream());

XDocument xDoc = XDocument.Load(new XmlNodeReader(xmlDoc));                          

String result = xDoc.Descendants(ns0 + "result").First().Value;

Questo ovviamente presuppone che ricevo la mia risposta indietro da un nome richiesta HttpWebRequest .

Non ci sono risposte molto buona e completa a questa domanda.

mi piacerebbe aggiungere solo per curiosità, che un estremamente semplice espressione XPath fa il lavoro in questo caso particolare:

normalize-space(/)

Questo è fatto facilmente in C # usando qualcosa come le due righe sotto:

        XPathNavigator navigator = document.CreateNavigator();

        string res = (string)navigator.Evaluate("normalize-space(/)");

Con la buona ottimizzazione del motore .NET XPath, la sua valutazione può anche essere efficiente.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top