2009-04-20 6 views
10

Mon exigence de base est d'obtenir la valeur de l'élément à partir du fichier XML, j'ai utilisé XMLDoxument.SelectSingleNode. Mon fichier XML contient un espace de nommage dans l'en-tête, j'ai donc utilisé NameSpaceManager pour ajouter un préfixe d'espace de noms et j'ai utilisé le préfixe pour obtenir cet élément particulier. Maintenant, dans mes fichiers XML, les espaces de noms varient, je ne veux pas faire de codage, est-il possible de trouver tous les espaces de noms et je peux l'ajouter à NameSpaceManager.comment je peux lister tout l'espace de noms en XML?

Merci.

+0

@Ruchita: Le problème avec cette approche est que les déclarations d'espaces de noms peuvent être écrasées (en XML 1.0, la déclaration d'espace de noms par défaut peut également être réinitialisée, en XML 1).1 toutes les déclarations d'espace de nom) –

Répondre

2

Votre problème de base pour récupérer des espaces de noms à partir d'un document Xml peut être résolu simplement en récupérant le NameTable du XmlDocument et en en créant un XmlNameSpaceManager. Toutefois, si vous souhaitez répertorier les espaces de noms à d'autres fins, vous devez vérifier la méthode GetNamespacesInScope exposée par la classe XmlNamespaceManager ainsi que la classe XPathNavigator.

Lorsque vous utilisez un XmlDocument, vous pouvez obtenir un XmlNamespaceManager de celui-ci par le code suivant:

//Instantiate an XmlDocument object. 
XmlDocument xmldoc = new XmlDocument(); 

//Load XML file into the XmlDocument object. 
xmldoc.Load("C:\\myFile.xml"); 

//Instantiate an XmlNamespaceManager object. 
XmlNamespaceManager nsMgr = new XmlNamespaceManager(xmldoc.NameTable); 

// Retrieve the namespaces into a Generic dictionary with string keys. 
IDictionary<string, string> dic = nsMgr.GetNamespacesInScope(XmlNamespaceScope.All); 

// Iterate through the dictionary. 

... 

In this article, Scott Hanselman présente un moyen d'utiliser cette méthode pour répertorier tous les espaces de noms dans un document à l'aide d'un XPathNavigator et en utilisant un pont LINQ.

+2

Cela ne semble pas fonctionner pour moi. Il y a beaucoup d'éléments dans le NameTable du document, mais plusieurs espaces de noms définis au début du document ne sont pas ajoutés au XmlNamespaceManager. Je continue d'obtenir "Namespace non défini" dans mes appels SelectNodes, à moins que j'ajoute manuellement les espaces de noms au gestionnaire. J'ai besoin d'une solution qui lit avec précision les espaces de noms définis dans le document XML, et les ajoute à mon gestionnaire d'espace de nom afin que je n'ai pas à les coder en dur. –

+0

@SeanWorle Il est un peu tard, mais consultez [Obtenir des espaces de noms à partir d'un document XML avec XPathDocument et LINQ to XML] (http://www.hanselman.com/blog/CommentView.aspx?guid=51861b63-526f-4572- ba84-2f24a1c7bd83), peut-être qu'il pourrait vous aider ou quelqu'un d'autre. – ErikE

+1

Le problème avec cette approche est qu'elle ignore les entrées "xmlns". –

7

Merci pour votre réponse rapide ...

Je pense que la version .Net que vous utilisez est doit être plus récente. J'utilise framework .Net 1.1 ... assez vieux :(..

Au moment où je ,, ai quelques exemples de code comme celui-ci .. dans le même but ...

XmlNodeList _xmlNameSpaceList = _xmlDocument.SelectNodes(@"//namespace::*[not(. = ../../namespace::*)]"); 

      _xmlNSmgr = new XmlNamespaceManager(_xmlDocument.NameTable);   

      foreach(XmlNode nsNode in _xmlNameSpaceList) 
      { 
       _xmlNSmgr.AddNamespace(nsNode.LocalName,nsNode.Value); 
      } 

Tous Les commentaires seront appréciés pour ajouter des connaissances à mon KB ... Merci

+0

bon vieux XPath, fonctionne parfaitement bien, il récupère tous les nœuds avec des espaces de noms. Merci – zulucoda

-2

Si vous cherchez un moyen rapide d'éviter le problème d'espace de noms, dépouillez les définitions d'espace de noms du Xml via un RegEx avant de faire un XmlDocument .LoadXml (bla) .C'est ce que je fais lors de l'analyse des pages XHTML en direct.Prend le temps de chargement de XmlDoc de 15 secondes à .15 secondes et fait en sorte que je n'ai pas à préfixer mes xpaths .

13

Les espaces de noms peuvent être trouvés n'importe où dans le document XML. Donc, pour extraire tous les espaces de noms et de les déclarer en XmlNamespaceManager je l'ai fait ce qui suit:

public static XmlNamespaceManager getAllNamespaces(XmlDocument xDoc) 
{ 
    XmlNamespaceManager result = new XmlNamespaceManager(xDoc.NameTable); 

    IDictionary<string, string> localNamespaces = null; 
    XPathNavigator xNav = xDoc.CreateNavigator(); 
    while (xNav.MoveToFollowing(XPathNodeType.Element)) 
    { 
     localNamespaces = xNav.GetNamespacesInScope(XmlNamespaceScope.Local); 
     foreach (var localNamespace in localNamespaces) 
     { 
      string prefix = localNamespace.Key; 
      if (string.IsNullOrEmpty(prefix)) 
        prefix = "DEFAULT"; 

      result.AddNamespace(prefix, localNamespace.Value); 
     } 
    } 

    return result; 
} 

Juste faire attention au cas d'espace de noms par défaut. J'ai redéfini l'espace de noms par défaut en tant que préfixe "DEFAULT" parce que j'ai rencontré des problèmes lors de la sélection de SelectSingleNode en utilisant le gestionnaire d'espace de nom retourné ci-dessus lors de l'interrogation de l'espace de noms par défaut. J'étais ma solution de contournement. Espérons que cela aide

0

Ruchita a publié la solution de travail pour XmlDocument. Mais je voulais faire la même chose avec XDocument. Voici le même avec XDocument:

var xml = XDocument.Load(filename); 
var xmlNameSpaceList = ((IEnumerable)xml.XPathEvaluate(@"//namespace::*[not(. = ../../namespace::*)]")).Cast<XAttribute>(); 
var xmlNSmgr = new XmlNamespaceManager(new NameTable()); 
foreach (var nsNode in xmlNameSpaceList) 
{ 
    xmlNSmgr.AddNamespace(nsNode.Name.LocalName, nsNode.Value); 
} 

Maintenant, vous pouvez utiliser XPath avec des espaces de noms, par exemple xml.XPathEvaluate("//test:p", xmlNSmgr).

Questions connexes