with namespace c# .net xml linq-to-xml xml-namespaces

c# - namespace - Cómo eliminar el atributo xmlns de un nodo distinto de la raíz en un XDocument



xml with namespace (2)

Situación

Estoy usando XDocument para intentar eliminar un atributo xmlns="" en el primer nodo interno :

<Root xmlns="http://my.namespace"> <Firstelement xmlns=""> <RestOfTheDocument /> </Firstelement> </Root>

Entonces, lo que quiero como resultado es:

<Root xmlns="http://my.namespace"> <Firstelement> <RestOfTheDocument /> </Firstelement> </Root>

Código

doc = XDocument.Load(XmlReader.Create(inStream)); XElement inner = doc.XPathSelectElement("/*/*[1]"); if (inner != null) { inner.Attribute("xmlns").Remove(); } MemoryStream outStream = new MemoryStream(); XmlWriter writer = XmlWriter.Create(outStream); doc.Save(writer); // <--- Exception occurs here

Problema

Al intentar guardar el documento, obtengo la siguiente excepción:

El prefijo '''' no se puede redefinir de '''' a '' http: //my.namespace '' dentro de la misma etiqueta de elemento de inicio.

¿Qué significa esto y qué puedo hacer para eliminar ese molesto xmlns="" ?

Notas

  • Quiero mantener el espacio de nombres del nodo raíz
  • Solo quiero que se eliminen esos xmlns específicos, no habrá otros atributos xmlns en el documento.

Actualizar

He intentado usar un código inspirado en las respuestas de esta pregunta :

inner = new XElement(inner.Name.LocalName, inner.Elements());

Cuando se realiza la depuración, el atributo xmlns desaparece, pero obtengo la misma excepción.


Creo que el código de abajo es lo que quieres. Debe colocar cada elemento en el espacio de nombres correcto y eliminar cualquier atributo xmlns='''' para los elementos afectados. La última parte es necesaria ya que de lo contrario, LINQ to XML básicamente intentará dejarle un elemento de

<!-- This would be invalid --> <Firstelement xmlns="" xmlns="http://my.namespace">

Aquí está el código:

using System; using System.Xml.Linq; class Test { static void Main() { XDocument doc = XDocument.Load("test.xml"); // All elements with an empty namespace... foreach (var node in doc.Root.Descendants() .Where(n => n.Name.NamespaceName == "")) { // Remove the xmlns='''' attribute. Note the use of // Attributes rather than Attribute, in case the // attribute doesn''t exist (which it might not if we''d // created the document "manually" instead of loading // it from a file.) node.Attributes("xmlns").Remove(); // Inherit the parent namespace instead node.Name = node.Parent.Name.Namespace + node.Name.LocalName; } Console.WriteLine(doc); // Or doc.Save(...) } }


No hay necesidad de ''eliminar'' el atributo xmlns vacío. La razón por la que se agrega el atributo xmlns vacío es porque el espacio de nombres de sus childnodes está vacío (= '''') y, por lo tanto, difiere de su nodo raíz. Agregar el mismo espacio de nombres a sus hijos también resolverá este ''efecto secundario''.

XNamespace xmlns = XNamespace.Get("http://my.namespace"); // wrong var doc = new XElement(xmlns + "Root", new XElement("Firstelement")); // gives: <Root xmlns="http://my.namespace"> <Firstelement xmlns="" /> </Root> // right var doc = new XElement(xmlns + "Root", new XElement(xmlns + "Firstelement")); // gives: <Root xmlns="http://my.namespace"> <Firstelement /> </Root>