2010-03-11 20 views
1

Je suis en train d'analyser un fichier xml:Pourquoi XElement tombe-t-il en analysant un fichier xml avec un xmlns?

<?xml version="1.0" encoding="utf-8" ?> 
<Root>  
    <att1 name="bob" age="unspecified" xmlns="http://foo.co.uk/nan">  
    </att1>  
</Root> 

En utilisant le code suivant:

XElement xDoc= XElement.Load(filename); 
var query = from c in xDoc.Descendants("att1").Attributes() select c; 
foreach (XAttribute a in query) 
{ 
    Console.WriteLine("{0}, {1}",a.Name,a.Value); 
} 

Rien est écrit à la console, sauf si je supprime xmlns = "http: // foo. co.uk/nan "du fichier xml, après quoi, j'obtiens une liste de noms d'attributs et de valeurs comme on pourrait s'y attendre, et comme j'en ai besoin!

Édition: formatage.

+0

Par ailleurs, il n'y a pas de point par écrit 'de c quelle que soit sélectionnez c'. – SLaks

+0

Donc il n'y en a pas! Merci :) Je l'ai choisi à partir d'une introduction très utile à LINQ to XML ici: http://www.microsoft.com/uk/msdn/nuggets/nugget/204/Querying-XML-in-C-with- LINQ-to-XML.aspx – zotty

Répondre

3

Vous devez utiliser le même espace de noms dans votre code:

XElement xDoc= XElement.Load(filename); 
XNamespace ns = "http://foo.co.uk/nan"; 
var query = from c in xDoc.Descendants(ns + "att1").Attributes() select c; 
foreach (XAttribute a in query) 
{ 
    Console.WriteLine("{0}, {1}",a.Name,a.Value); 
} 

Les attributs ne prennent pas l'espace de noms par défaut (xmlns=....), de sorte que vous n'avez pas besoin de les qualifier. La balise d'espace de nom (xmln:tags=....) est purement locale à l'utilisation du document ou de l'API, les noms sont en réalité namespace + nom local, donc vous devez toujours spécifier l'espace de noms.

+0

Cela a fait le tour parfaitement, merci. Étant donné que l'espace de noms est susceptible de changer entre les fichiers xml, je suppose que vous devez charger le fichier sous forme de chaîne, puis recherchez l'espace de noms et le déclarer dans le code? – zotty

+0

@zotty Aucune analyse de chaîne n'est nécessaire si vous interrogez le LocalName comme indiqué dans ma réponse. –

+0

@zotty: Si les espaces de noms varient, votre code sera plus détaillé, et il manque vraiment le point des espaces de noms (le nom d'un noeud est un espace de noms + un nom local), mais cela est parfois nécessaire. – Richard

1

Vous devez spécifier l'espace de noms dans le présent appel, comme Descendants:

XNamespace ns = "http://foo.co.uk/nan"; 
foreach (XAttribute a in xDoc.Descendants(ns + "att1")) 
{ 
    Console.WriteLine("{0}, {1}",a.Name,a.Value); 
} 
2

Votre appel à Descendants est un élément Requêter pour nom « att1 » dans aucun espace de noms.

Si vous appelez Descendants("{http://foo.co.uk/nan}att1"), vous devez sélectionner l'élément namespaced mais pas l'élément non-namespaced.

Vous pouvez sélectionner des éléments nommés « att1 » dans tout ou aucun espace de noms comme ceci:

var query = from c in xDoc.Descendants() where c.Name.LocalName == "att1" select c.Attributes;