O que é uma boa maneira de encontrar um valor específico em um documento XML usando C #?

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

  •  22-08-2019
  •  | 
  •  

Pergunta

Eu estou chamando um WebService exposta pela Oracle que aceita uma entrada de um ItemID e retorna para mim, o correspondente número do item. Quero agarrar o Número de artigo que tenha sido devolvido para fora do XML contido na resposta.

Os olhares XML como este:

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

Estou interessado em pegar apenas o <ns0:result>1010603</ns0:result> particularmente somente a 1.010.603.

Eu não fiz um monte de XML parsing trabalho usando C # e eu estou brincando com alguns métodos diferentes até agora. O que é a maneira recomendada para fazer isso?

Eu estou no VS2008 (assim XPath está disponível etc.)

Foi útil?

Solução

Eu pessoalmente uso LINQ to XML, porque acho que mais fácil de lidar do que XPath, particularmente quando namespaces estão envolvidos. Você faria algo como:

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

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

Note que doc aqui é esperado para ser um XDocument , não XmlDocument . (Meu palpite é que é por isso que não estava aparecendo para você.)

Outras dicas

fwiw você pode enganar a questão namespace com um XPath como este: //*[local-name()='result']

Se você não quiser ir para Linq você poderia usar XPathDocument para recuperar o 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 tem uma pegada de memória menor e é mais provável mais rápido em seu cenário de XmlDocument. XmlDocument acumula-se um modelo de objeto completa do documento XML na memória enquanto XPathDocument não faz isso.

Em cima da minha cabeça, o seguinte deve funcionar:

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

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

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

Os olhares de código namespace como este:

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

Você precisa usar o gerenciador de namespace porque o documento XML tem namespaces associados, e XPath usa isso em consulta resolução.

Para resolver isso, eu usei a resposta de Jon Skeet. Aqui está o código que eu tinha que implementar para fazer este trabalho (para o benefício futuro de qualquer outra pessoa).

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;

Isto, obviamente, pressupõe que eu estou recebendo minha resposta de volta a partir de um HttpWebRequest chamado pedido .

Existem muito boas e completas respostas a esta pergunta.

Eu adicionaria apenas por curiosidade, que uma expressão XPath extremamente simples faz o trabalho , neste caso particular:

normalize-space(/)

Isso é facilmente feito em C # usando algo parecido com as duas linhas abaixo:

        XPathNavigator navigator = document.CreateNavigator();

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

Com a boa otimização do motor .NET XPath, a sua avaliação pode até ser eficiente.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top