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