Pergunta

Estou tendo problemas para criar um documento XML que contém um espaço para nome padrão e um espaço de nome nomeado, difícil de explicar mais fácil de mostrar o que estou tentando produzir ...

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

Mas o que eu acabo é isso ...

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

O código que escrevi para produzir este snippet xml é este ...

  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")));

com base em um Exemplo no MSDN

****EDITAR****

Ok, com um pouco mais de experimentação, agora estou muito confuso sobre como os namespaces XML funcionam ....

Se eu remover o AW + Theattribute, eu pego o que eu estava procurando ... mas agora parece que o que eu estava procurando não é realmente o que eu esperava. Eu pensei que os namespaces eram herdados de seus pais, isso também não é verdadeiro para atributos? Porque, esse código para ler os atributos não funciona como eu esperava ...

  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");

No entanto, se eu remover o AW + no atributo, está bem, levando -me a assumir que não posso ter atributos no espaço de nome padrão. Isso está correto?

Foi útil?

Solução

Boa pergunta. Eu cavei um pouco e encontrei Este pedaço da especificação XML:

Uma declaração de namespace padrão se aplica a todos os nomes de elementos não prefixados em seu escopo. As declarações de namespace padrão não se aplicam diretamente aos nomes de atributos; A interpretação dos atributos não prefixados é determinada pelo elemento em que eles aparecem.

Mais tarde, continua a dar este exemplo:

Por exemplo, cada uma das tags de elementos vazios ruins é ilegal a seguir:

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

No entanto, cada um dos seguintes é legal, o segundo porque o espaço para nome padrão não se aplica aos nomes de atributos:

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

Então, basicamente, parece que os nomes de atributos não recebem namespaces por padrão, o que explica tudo o que você viu :)

Outras dicas

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;

Para qualquer outra pessoa que passou 2 dias tentando encontrar uma resposta.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top