3 votes

XML SelectNode() ne renvoie rien. Pourquoi l'espace de nom est-il important ?

J'ai un code pour obtenir les noeuds d'un élément Root :

xmlNodes = rootElement.SelectNodes("DefinitionName");

Il ne renvoie pas les noeuds qui existent. Dans le débogueur, je peux développer rootElement pour trouver DefinitionName. Apparemment, le problème vient du fait que le fichier a un espace de nom défini (voir XML ci-dessous). MSDN dit que je dois faire quelque chose comme ça pour que les noeuds reviennent :

Note : Cela n'a rien à voir avec mon code. C'est l'exemple de MSDN :

XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("ab", "http://www.lucernepublishing.com");
XmlNodeList nodelist = doc.SelectNodes("//ab:book", nsmgr);

J'ai deux questions :

  1. Pourquoi l'espace de noms est-il important ? Si je veux un noeud, et qu'il existe, donnez-le moi.
  2. Mon application traite de nombreux fichiers XML. Comment suis-je censé spécifier l'espace de nom ( nsmgr.AddNamespace() ) ? Dois-je d'abord analyser le fichier pour l'obtenir ?

Je ne peux pas m'empêcher de penser que je prends le chemin le plus long et le plus angoissant pour y arriver.

C'est le XML :

    <?xml version="1.0" encoding="utf-8"?>
    <SessionStateInfo xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
    z:Id="1" z:Type="Company.Apps.MoreHere.Session.SessionStateInfo"
    z:Assembly="assembly info here"
    xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/"
    xmlns="http://schemas.datacontract.org/2004/07/MoreHere.Session">
      <CoaterNumber>25</CoaterNumber>
      <DefinitionName z:Id="2">Two Line</DefinitionName>
      <EnableManualMode>true</EnableManualMode>

4voto

Ian Roberts Points 59836
<SessionStateInfo ....
    xmlns="http://schemas.datacontract.org/2004/07/MoreHere.Session">

signifie que cet élément et tous ses descendants se trouvent dans l'ensemble de l'espace de travail. http://schemas.datacontract.org/2004/07/MoreHere.Session espace de noms. Puisque les noms non fixés dans un XPath font toujours référence à des éléments dans no vous devrez lier cet URI à un préfixe et utiliser ce préfixe dans votre XPath, même si aucun préfixe n'est utilisé dans le document.

XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("mhs", "http://schemas.datacontract.org/2004/07/MoreHere.Session");
xmlNodes = rootElement.SelectNodes("mhs:DefinitionName", nsmgr);

Si vous savez que le ou les éléments que vous recherchez auront toujours le même nom local mais qu'ils peuvent ou non avoir un espace de noms (ou qu'ils peuvent avoir des espaces de noms différents), vous pouvez utiliser des astuces XPath telles que

rootElement.SelectNodes("*[local-name() = 'DefinitionName']");

2voto

x0n Points 26002

C'est important car s'il y a un espace de noms attaché, alors "NomDéfinition" n'est pas suffisant. Imaginez que l'on vous donne une liste de personnes, toutes portant le prénom Jean :

  • John Smith
  • John Jones
  • John Murphy

Ce que vous faites est l'équivalent de demander "John" au lieu de "John Smith", par exemple.

1voto

Jim Points 1780

Ce n'est pas exactement la réponse à la question mais cela peut être une solution alternative en utilisant XDocument

using System;
using System.Dynamic;
using System.Xml.Linq;
using Microsoft.CSharp.RuntimeBinder;
using System.Linq;

namespace ConsoleApplication8
{
    class Program
    {
        static void Main(string[] args)
        {
            XDocument document = XDocument.Load("SessionStateInfo.xml");
            XNamespace nameSpace = document.Root.GetDefaultNamespace();
            XElement node = document.Descendants(nameSpace + "DefinitionName").FirstOrDefault();   

            if (node != null)
            {
                Console.WriteLine("Cool! XDocument rocks! value: {0}", node.Value);
            }
            else
            {
                Console.WriteLine("Spoot! Didn't find it!");
            }
        }      
    }       
}

Cela semble fonctionner, que l'espace de noms par défaut soit spécifié ou non.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X