¿Qué es una buena manera de encontrar un valor específico en un documento XML utilizando C #?

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

  •  22-08-2019
  •  | 
  •  

Pregunta

Voy a llamar a un servicio web expuesto por Oracle que acepta una entrada de un ItemID y vuelve a mí el número de artículo correspondiente. Quiero agarrar el número del elemento que ha sido retornadas de XML contenida en la respuesta.

El XML es el siguiente:

<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>

Estoy interesado en agarrar sólo el <ns0:result>1010603</ns0:result> particular sólo el 1.010.603.

No he hecho un montón de análisis sintáctico XML trabajo usando C # y estoy jugando un poco con algunos métodos diferentes hasta el momento. ¿Cuál es el método recomendado para hacer esto?

Estoy en VS2008 (por lo XPath está disponible, etc.)

¿Fue útil?

Solución

Me personalmente uso de LINQ para XML, porque me parece que más fácil de tratar que XPath, sobre todo cuando se trata de espacios de nombres. Se podría hacer algo como:

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

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

Se espera que la Nota doc aquí para ser un XDocument , no XmlDocument . (Mi conjetura es que esto es por qué no se muestra para usted.)

Otros consejos

fwiw se puede engañar a la cuestión de espacio de nombres con un XPath como esto: //*[local-name()='result']

Si no desea ir para LINQ podría utilizar XPathDocument para recuperar el valor:

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 tiene una huella de memoria más baja y es más probable más rápido en su escenario de XmlDocument. XmlDocument se acumula un modelo de objetos completa del documento XML en la memoria mientras que XPathDocument no hacerlo.

De la parte superior de mi cabeza, lo siguiente debería funcionar:

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

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

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

El código de espacio de nombres es el siguiente:

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

Es necesario utilizar el gestor de espacio de nombres debido a que el documento XML tiene espacios de nombres asociados a ella, y XPath utiliza esta en la resolución de consultas.

Para solucionar esto, he usado la respuesta de Jon Skeet. Aquí está el código que tenía que poner en práctica para hacer este trabajo (para cualquier otra persona de beneficio en el 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;

Por supuesto, esto supone que yo estoy haciendo mi respuesta de vuelta de un solicitud HttpWebRequest nombre .

Hay respuestas muy buenas y completas a esta pregunta.

Yo añadiría sólo por curiosidad, que una expresión XPath extremadamente simple hace el trabajo en este caso particular:

normalize-space(/)

Esto se hace fácilmente en C # usando algo como las dos líneas siguientes:

        XPathNavigator navigator = document.CreateNavigator();

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

Con la buena optimización del motor de .NET XPath, su evaluación, incluso puede ser eficiente.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top