Qu'est-ce qu'un bon moyen de trouver une valeur spécifique dans un document XML en utilisant C #?

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

  •  22-08-2019
  •  | 
  •  

Question

J'appelle un WebService exposé par Oracle qui accepte une entrée d'un ItemID et retourne à moi le numéro d'article correspondant. Je veux saisir le numéro d'article qui a été retourné sur le XML contenu dans la réponse.

Le XML ressemble à ceci:

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

Je suis intéressé à saisir que le <ns0:result>1010603</ns0:result> particulier que le 1010603.

Je ne l'ai pas fait beaucoup de XML d'analyse syntaxique de travail en utilisant C # et je suis jouer avec quelques méthodes différentes jusqu'à présent. Quelle est la méthode recommandée pour le faire?

Je suis sur VS2008 (si XPath est disponible, etc.)

Était-ce utile?

La solution

Je personnellement utiliser LINQ pour XML, parce que je trouve cela plus facile à traiter que XPath, en particulier lorsque les espaces de noms sont impliqués. Tu ferais quelque chose comme:

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

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

Notez que doc ici devrait être XDocument , pas XmlDocument . (Je pense que c'est pourquoi il ne montrait pas pour vous.)

Autres conseils

FWIW vous pouvez tricher le problème d'espace de noms avec un XPath comme ceci: //*[local-name()='result']

Si vous ne voulez pas aller pour LINQ, vous pouvez utiliser XPathDocument pour récupérer la valeur:

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 a une empreinte mémoire plus faible et est très probablement plus rapide dans votre scénario que XmlDocument. XmlDocument construit un modèle objet complet de votre document XML en mémoire alors que XPathDocument ne le fait pas.

Du haut de ma tête, ce qui suit devrait fonctionner:

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

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

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

Le code d'espace de nom ressemble à ceci:

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

Vous devez utiliser le gestionnaire d'espace de noms parce que le document XML a namespaces qui y sont associés, et XPath utilise dans la résolution de la requête.

Pour résoudre ce problème, je la réponse de Jon Skeet. Voici le code que je devais mettre en œuvre pour faire ce travail (pour le bénéfice futur de quelqu'un d'autre).

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;

Bien sûr, cela suppose que je reçois ma réponse en retour d'un HttpWebRequest nommé demande .

Il y a de très bonnes réponses et complètes à cette question.

Je rajouterais juste par curiosité, qu'une expression XPath extrêmement simple fait le travail dans ce cas particulier:

normalize-space(/)

Ceci est facilement fait en C # en utilisant quelque chose comme les deux lignes ci-dessous:

        XPathNavigator navigator = document.CreateNavigator();

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

Avec la bonne optimisation du moteur XPath .NET, son évaluation peut même être efficace.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top