2009-08-05 7 views
3

Je ne parviens pas à créer un document XML qui contient un espace de noms par défaut et un espace de noms nommé, difficile à expliquer plus facile de montrer exactement ce que je suis en train de produire ...XElement espace de noms par défaut des attributs fournit un comportement inattendu

<Root xmlns="http://www.adventure-works.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:SchemaLocation="http://www.SomeLocatation.Com/MySchemaDoc.xsd"> 
    <Book title="Enders Game" author="Orson Scott Card" /> 
    <Book title="I Robot" author="Isaac Asimov" /> 
</Root> 

mais ce que je finis avec ... est-ce

<Root xmlns="http://www.adventure-works.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:SchemaLocation="http://www.SomeLocatation.Com/MySchemaDoc.xsd"> 
    <Book p3:title="Enders Game" p3:author="Orson Scott Card" xmlns:p3="http://www.adventure-works.com" /> 
    <Book p3:title="I Robot" p3:author="Isaac Asimov" xmlns:p3="http://www.adventure-works.com" /> 
</Root> 

Le code que j'ai écrit pour produire cet extrait XML est ce ...

XNamespace aw = "http://www.adventure-works.com"; 
    XNamespace xsi = "http://www.w3.org/2001/XMLSchema-instance"; 
    XElement root = new XElement(aw + "Root", 
     new XAttribute("xmlns", "http://www.adventure-works.com"), 
     new XAttribute(XNamespace.Xmlns + "xsi", "http://www.w3.org/2001/XMLSchema-instance"), 
     new XAttribute(xsi + "SchemaLocation", "http://www.SomeLocatation.Com/MySchemaDoc.xsd"), 

     new XElement(aw + "Book", 
     new XAttribute(aw + "title", "Enders Game"), 
     new XAttribute(aw + "author", "Orson Scott Card")), 
     new XElement(aw + "Book", 
     new XAttribute(aw + "title", "I Robot"), 
     new XAttribute(aw + "author", "Isaac Asimov"))); 

basé sur une example on MSDN

**** **** EDIT

Ok, avec un peu plus d'expériences que je suis très confus sur la façon dont XML les espaces de noms ....

si je enlever l'aw + theattribute je reçois ce que j'étais après ... mais maintenant il semble que ce que j'étais après n'est pas vraiment ce que je m'attendais. Je pensais que les espaces de noms étaient hérités de leurs parents, n'est-ce pas aussi vrai pour les attributs? parce que, ce code pour lire les attributs ne fonctionne pas comme je m'y attendais ...

XElement xe = XElement.Parse(textBox1.Text); 
    XNamespace aw = "http://www.adventure-works.com"; 
    var qry = from x in xe.Descendants(aw + "Book") 
      select (string)x.Attribute(aw + "author"); 

Cependant, si je retire la aw + sur l'attribut its ok, me conduit à supposer que je ne peux pas avoir des attributs dans l'espace de noms par défaut . Est-ce correct?

Répondre

6

Bonne question. Je creusais un peu, et trouvé this bit of the XML spec:

Un espace de noms par défaut déclaration applique à tous les éléments sans préfixe noms dans son champ d'application. Les déclarations d'espace de noms par défaut ne s'appliquent pas directement aux noms d'attribut; ; l'interprétation des attributs non préfixés est déterminée par l'élément sur lequel ils apparaissent.

Il va plus loin pour donner cet exemple:

Par exemple, chacun des mauvais balises élément vide est illégal dans les domaines suivants:

<!-- http://www.w3.org is bound to n1 and n2 --> 
<x xmlns:n1="http://www.w3.org" 
    xmlns:n2="http://www.w3.org" > 
    <bad a="1"  a="2" /> 
    <bad n1:a="1" n2:a="2" /> 
</x> 

Cependant , chacun des suivants est légal, le second parce que l'espace de nom par défaut ne s'applique pas aux noms d'attribut:

<!-- http://www.w3.org is bound to n1 and is the default --> 
<x xmlns:n1="http://www.w3.org" 
    xmlns="http://www.w3.org" > 
    <good a="1"  b="2" /> 
    <good a="1"  n1:a="2" /> 
</x> 

Donc, fondamentalement, il semble que les noms d'attributs ne reçoivent pas les espaces de noms par défaut, ce qui explique tout ce que vous avez vu :)

+0

très intéressant en effet. Les espaces de noms XML ne sont pas amusants ;-) –

+1

D'accord, bien que LINQ to XML les rende plus agréables à utiliser que tout autre framework que j'ai vu. –

1
XElement doc = XElement.Parse(ToXml()); 
doc.DescendantsAndSelf().Attributes().Where(a => a.IsNamespaceDeclaration).Remove(); 
var ele = doc.DescendantsAndSelf(); 
foreach (var el in ele) 
    el.Name = ns != null ? ns + el.Name.LocalName : el.Name.LocalName; 

Pour quelqu'un d'autre qui a passé 2 jours à essayer de trouver un répondre.

Questions connexes