El espacio de nombres predeterminado de XElement en los atributos proporciona un comportamiento inesperado

StackOverflow https://stackoverflow.com/questions/1231396

Pregunta

Tengo problemas para crear un documento XML que contenga un espacio de nombres predeterminado y un espacio de nombres con nombre, difícil de explicar, es más fácil mostrar lo que estoy tratando de producir ...

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

pero con lo que termino es esto ...

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

El código que escribí para producir este fragmento XML es 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")));

basado en un ejemplo en MSDN

**** EDITAR ****

Ok, con algo más de experimentación ahora estoy muy confundido sobre cómo funcionan los espacios de nombres XML ...

si elimino el atributo aw + obtengo lo que buscaba ... pero ahora parece que lo que buscaba no es realmente lo que esperaba. Pensé que los espacios de nombres fueron heredados de sus padres, ¿no es esto también cierto para los atributos? porque este código para leer los atributos no funciona como esperaba ...

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

Sin embargo, si elimino el aw + en el atributo está bien, lo que me lleva a suponer que no puedo tener atributos en el espacio de nombres predeterminado. ¿Es esto correcto?

¿Fue útil?

Solución

Buena pregunta. Busqué un poco y encontré este bit de la especificación XML :

  

Una declaración de espacio de nombres predeterminada   se aplica a todos los elementos no prefijados   nombres dentro de su alcance. Defecto   las declaraciones de espacio de nombres no se aplican   directamente a los nombres de atributos; la   interpretación de no prefijado   los atributos están determinados por el   elemento en el que aparecen.

Más adelante pasa a dar este ejemplo:

  

Por ejemplo, cada una de las etiquetas incorrectas de elementos vacíos es ilegal en lo siguiente:

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

Sin embargo, cada uno de los siguientes es legal, el segundo porque el espacio de nombres predeterminado no > aplicar a nombres 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>

Entonces, básicamente, parece que los nombres de atributo no obtienen espacios de nombres por defecto, lo que explica todo lo que has visto :)

Otros consejos

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 cualquier otra persona que haya pasado 2 días tratando de encontrar una respuesta.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top