write read node leer ejemplo create crear c# xml

read - ¿Cómo eliminar todos los espacios de nombres de XML con C#?



xml c# ejemplo (29)

Estoy buscando la solución limpia, elegante e inteligente para eliminar espacios de nombres de todos los elementos XML? ¿Cómo funcionaría para que se vea así?

Interfaz definida:

public interface IXMLUtils { string RemoveAllNamespaces(string xmlDocument); }

Ejemplo de XML para eliminar NS de:

<?xml version="1.0" encoding="utf-16"?> <ArrayOfInserts xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <insert> <offer xmlns="http://schema.peters.com/doc_353/1/Types">0174587</offer> <type2 xmlns="http://schema.peters.com/doc_353/1/Types">014717</type2> <supplier xmlns="http://schema.peters.com/doc_353/1/Types">019172</supplier> <id_frame xmlns="http://schema.peters.com/doc_353/1/Types" /> <type3 xmlns="http://schema.peters.com/doc_353/1/Types"> <type2 /> <main>false</main> </type3> <status xmlns="http://schema.peters.com/doc_353/1/Types">Some state</status> </insert> </ArrayOfInserts>

Después de llamar a RemoveAllNamespaces (xmlWithLotOfNs), deberíamos obtener:

<?xml version="1.0" encoding="utf-16"?> <ArrayOfInserts> <insert> <offer >0174587</offer> <type2 >014717</type2> <supplier >019172</supplier> <id_frame /> <type3 > <type2 /> <main>false</main> </type3> <status >Some state</status> </insert> </ArrayOfInserts>

El idioma de solución preferido es C # en .NET 3.5 SP1.


Aquí está mi versión de VB.NET de Dexter Legaspi C # Version

Shared Function RemoveAllNamespaces(ByVal e As XElement) As XElement Return New XElement(e.Name.LocalName, New Object() {(From n In e.Nodes Select If(TypeOf n Is XElement, RemoveAllNamespaces(TryCast(n, XElement)), n)), If(e.HasAttributes, (From a In e.Attributes Select a), Nothing)}) End Function


Bueno, aquí está la respuesta final. He utilizado la gran idea de Jimmy (que lamentablemente no está completa) y completa la función de recursión para que funcione correctamente.

Basado en la interfaz:

string RemoveAllNamespaces(string xmlDocument);

Represento aquí la solución final limpia y universal de C # para eliminar espacios de nombres XML:

//Implemented based on interface, not part of algorithm public static string RemoveAllNamespaces(string xmlDocument) { XElement xmlDocumentWithoutNs = RemoveAllNamespaces(XElement.Parse(xmlDocument)); return xmlDocumentWithoutNs.ToString(); } //Core recursion function private static XElement RemoveAllNamespaces(XElement xmlDocument) { if (!xmlDocument.HasElements) { XElement xElement = new XElement(xmlDocument.Name.LocalName); xElement.Value = xmlDocument.Value; foreach (XAttribute attribute in xmlDocument.Attributes()) xElement.Add(attribute); return xElement; } return new XElement(xmlDocument.Name.LocalName, xmlDocument.Elements().Select(el => RemoveAllNamespaces(el))); }

Funciona al 100%, pero no lo he probado demasiado, por lo que puede que no cubra algunos casos especiales ... Pero es una buena base para comenzar.


Eso hará el truco :-)

foreach (XElement XE in Xml.DescendantsAndSelf()) { // Stripping the namespace by setting the name of the element to it''s localname only XE.Name = XE.Name.LocalName; // replacing all attributes with attributes that are not namespaces and their names are set to only the localname XE.ReplaceAttributes((from xattrib in XE.Attributes().Where(xa => !xa.IsNamespaceDeclaration) select new XAttribute(xattrib.Name.LocalName, xattrib.Value))); }


Esta es una solución basada en la respuesta aceptada por Peter Stegnar.

Lo usé, pero (como comentaron andygjp y John Saunders) su código ignora los atributos .

También tenía que ocuparme de los atributos, así que adapté su código. La versión de Andy era Visual Basic, esto sigue siendo c #.

Sé que ha pasado un tiempo, pero tal vez le ahorrará a alguien algún día.

private static XElement RemoveAllNamespaces(XElement xmlDocument) { XElement xmlDocumentWithoutNs = removeAllNamespaces(xmlDocument); return xmlDocumentWithoutNs; } private static XElement removeAllNamespaces(XElement xmlDocument) { var stripped = new XElement(xmlDocument.Name.LocalName); foreach (var attribute in xmlDocument.Attributes().Where( attribute => !attribute.IsNamespaceDeclaration && String.IsNullOrEmpty(attribute.Name.NamespaceName))) { stripped.Add(new XAttribute(attribute.Name.LocalName, attribute.Value)); } if (!xmlDocument.HasElements) { stripped.Value = xmlDocument.Value; return stripped; } stripped.Add(xmlDocument.Elements().Select( el => RemoveAllNamespaces(el))); return stripped; }


Esto funcionó para mí.

FileStream fs = new FileStream(filePath, FileMode.Open); StreamReader sr = new StreamReader(fs); DataSet ds = new DataSet(); ds.ReadXml(sr); ds.Namespace = ""; string outXML = ds.GetXml(); ds.Dispose(); sr.Dispose(); fs.Dispose();


La respuesta más útil etiquetada tiene dos defectos:

  • Ignora los atributos
  • No funciona con elementos de "modo mixto"

Aquí está mi opinión sobre esto:

public static XElement RemoveAllNamespaces(XElement e) { return new XElement(e.Name.LocalName, (from n in e.Nodes() select ((n is XElement) ? RemoveAllNamespaces(n as XElement) : n)), (e.HasAttributes) ? (from a in e.Attributes() where (!a.IsNamespaceDeclaration) select new XAttribute(a.Name.LocalName, a.Value)) : null); }

Código de muestra here .


La respuesta obligatoria usando XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="no" encoding="UTF-8"/> <xsl:template match="/|comment()|processing-instruction()"> <xsl:copy> <xsl:apply-templates/> </xsl:copy> </xsl:template> <xsl:template match="*"> <xsl:element name="{local-name()}"> <xsl:apply-templates select="@*|node()"/> </xsl:element> </xsl:template> <xsl:template match="@*"> <xsl:attribute name="{local-name()}"> <xsl:value-of select="."/> </xsl:attribute> </xsl:template> </xsl:stylesheet>


Las respuestas de Jimmy y Peter fueron de gran ayuda, pero en realidad eliminaron todos los atributos, así que hice una pequeña modificación:

Imports System.Runtime.CompilerServices Friend Module XElementExtensions <Extension()> _ Public Function RemoveAllNamespaces(ByVal element As XElement) As XElement If element.HasElements Then Dim cleanElement = RemoveAllNamespaces(New XElement(element.Name.LocalName, element.Attributes)) cleanElement.Add(element.Elements.Select(Function(el) RemoveAllNamespaces(el))) Return cleanElement Else Dim allAttributesExceptNamespaces = element.Attributes.Where(Function(attr) Not attr.IsNamespaceDeclaration) element.ReplaceAttributes(allAttributesExceptNamespaces) Return element End If End Function End Module


Ligeramente modificada la respuesta de Peter, esto también funcionaría bien para el atributo, incluyendo eliminar el espacio de nombres y el prefijo. Un poco triste por el código se ve un poco feo.

private static XElement RemoveAllNamespaces(XElement xmlDocument) { if (!xmlDocument.HasElements) { XElement xElement = new XElement(xmlDocument.Name.LocalName); xElement.Value = xmlDocument.Value; foreach (XAttribute attribute in xmlDocument.Attributes()) { xElement.Add(new XAttribute(attribute.Name.LocalName, attribute.Value)); } return xElement; } else { XElement xElement = new XElement(xmlDocument.Name.LocalName, xmlDocument.Elements().Select(el => RemoveAllNamespaces(el))); foreach (XAttribute attribute in xmlDocument.Attributes()) { xElement.Add(new XAttribute(attribute.Name.LocalName, attribute.Value)); } return xElement; } }


Me gustó mucho dónde iba así que lo traduje a un método de extensión "fluido":

/// <summary> /// Returns the specified <see cref="XElement"/> /// without namespace qualifiers on elements and attributes. /// </summary> /// <param name="element">The element</param> public static XElement WithoutNamespaces(this XElement element) { if (element == null) return null; #region delegates: Func<XNode, XNode> getChildNode = e => (e.NodeType == XmlNodeType.Element) ? (e as XElement).WithoutNamespaces() : e; Func<XElement, IEnumerable<XAttribute>> getAttributes = e => (e.HasAttributes) ? e.Attributes() .Where(a => !a.IsNamespaceDeclaration) .Select(a => new XAttribute(a.Name.LocalName, a.Value)) : Enumerable.Empty<XAttribute>(); #endregion return new XElement(element.Name.LocalName, element.Nodes().Select(getChildNode), getAttributes(element)); }

El enfoque "fluido" me permite hacer esto:

var xml = File.ReadAllText(presentationFile); var xDoc = XDocument.Parse(xml); var xRoot = xDoc.Root.WithoutNamespaces();


Otra solución que tiene en cuenta la posibilidad de entrelazar los nodos TEXT y ELEMENT, por ejemplo:

<parent> text1 <child1/> text2 <child2/> </parent>

Código:

using System.Linq; namespace System.Xml.Linq { public static class XElementTransformExtensions { public static XElement WithoutNamespaces(this XElement source) { return new XElement(source.Name.LocalName, source.Attributes().Select(WithoutNamespaces), source.Nodes().Select(WithoutNamespaces) ); } public static XAttribute WithoutNamespaces(this XAttribute source) { return !source.IsNamespaceDeclaration ? new XAttribute(source.Name.LocalName, source.Value) : default(XAttribute); } public static XNode WithoutNamespaces(this XNode source) { return source is XElement ? WithoutNamespaces((XElement)source) : source; } } }


Para que los atributos funcionen, el ciclo for para agregar atributos debe ir después de la recursión, también es necesario verificar si IsNamespaceDeclaration:

private static XElement RemoveAllNamespaces(XElement xmlDocument) { XElement xElement; if (!xmlDocument.HasElements) { xElement = new XElement(xmlDocument.Name.LocalName) { Value = xmlDocument.Value }; } else { xElement = new XElement(xmlDocument.Name.LocalName, xmlDocument.Elements().Select(RemoveAllNamespaces)); } foreach (var attribute in xmlDocument.Attributes()) { if (!attribute.IsNamespaceDeclaration) { xElement.Add(attribute); } } return xElement; }


Puedes hacerlo usando Linq:

public static string RemoveAllNamespaces(string xmlDocument) { var xml = XElement.Parse(xmlDocument); xml.Descendants().Select(o => o.Name = o.Name.LocalName).ToArray(); return xml.ToString(); }


Recógelo nuevamente, en C # - línea agregada para copiar los atributos:

static XElement stripNS(XElement root) { XElement res = new XElement( root.Name.LocalName, root.HasElements ? root.Elements().Select(el => stripNS(el)) : (object)root.Value ); res.ReplaceAttributes( root.Attributes().Where(attr => (!attr.IsNamespaceDeclaration))); return res; }


Sé que esta pregunta está supuestamente resuelta, pero no estaba totalmente satisfecho con la forma en que se implementó. Encontré otra fuente aquí en los blogs de MSDN que tiene una clase XmlTextWriter reemplazada que elimina los espacios de nombres. Lo modifiqué un poco para obtener otras cosas que quería, como formatear y preservar el elemento raíz. Esto es lo que tengo en mi proyecto en este momento.

http://blogs.msdn.com/b/kaevans/archive/2004/08/02/206432.aspx

Clase

/// <summary> /// Modified XML writer that writes (almost) no namespaces out with pretty formatting /// </summary> /// <seealso cref="http://blogs.msdn.com/b/kaevans/archive/2004/08/02/206432.aspx"/> public class XmlNoNamespaceWriter : XmlTextWriter { private bool _SkipAttribute = false; private int _EncounteredNamespaceCount = 0; public XmlNoNamespaceWriter(TextWriter writer) : base(writer) { this.Formatting = System.Xml.Formatting.Indented; } public override void WriteStartElement(string prefix, string localName, string ns) { base.WriteStartElement(null, localName, null); } public override void WriteStartAttribute(string prefix, string localName, string ns) { //If the prefix or localname are "xmlns", don''t write it. //HOWEVER... if the 1st element (root?) has a namespace we will write it. if ((prefix.CompareTo("xmlns") == 0 || localName.CompareTo("xmlns") == 0) && _EncounteredNamespaceCount++ > 0) { _SkipAttribute = true; } else { base.WriteStartAttribute(null, localName, null); } } public override void WriteString(string text) { //If we are writing an attribute, the text for the xmlns //or xmlns:prefix declaration would occur here. Skip //it if this is the case. if (!_SkipAttribute) { base.WriteString(text); } } public override void WriteEndAttribute() { //If we skipped the WriteStartAttribute call, we have to //skip the WriteEndAttribute call as well or else the XmlWriter //will have an invalid state. if (!_SkipAttribute) { base.WriteEndAttribute(); } //reset the boolean for the next attribute. _SkipAttribute = false; } public override void WriteQualifiedName(string localName, string ns) { //Always write the qualified name using only the //localname. base.WriteQualifiedName(localName, null); } }

Uso

//Save the updated document using our modified (almost) no-namespace XML writer using(StreamWriter sw = new StreamWriter(this.XmlDocumentPath)) using(XmlNoNamespaceWriter xw = new XmlNoNamespaceWriter(sw)) { //This variable is of type `XmlDocument` this.XmlDocumentRoot.Save(xw); }


Sin recurrir a una solución basada en XSLT, si desea una solución limpia, elegante e inteligente, necesitaría un poco de apoyo del marco, en particular, el patrón de visitantes podría hacer esto muy fácil. Lamentablemente, no está disponible aquí.

Lo he implementado inspirado en ExpressionVisitor de LINQ para tener una estructura similar. Con esto, puede aplicar el patrón de visitante a objetos XML (LINQ-to-). (He hecho pruebas limitadas sobre esto pero funciona bien por lo que puedo decir)

public abstract class XObjectVisitor { public virtual XObject Visit(XObject node) { if (node != null) return node.Accept(this); return node; } public ReadOnlyCollection<XObject> Visit(IEnumerable<XObject> nodes) { return nodes.Select(node => Visit(node)) .Where(node => node != null) .ToList() .AsReadOnly(); } public T VisitAndConvert<T>(T node) where T : XObject { if (node != null) return Visit(node) as T; return node; } public ReadOnlyCollection<T> VisitAndConvert<T>(IEnumerable<T> nodes) where T : XObject { return nodes.Select(node => VisitAndConvert(node)) .Where(node => node != null) .ToList() .AsReadOnly(); } protected virtual XObject VisitAttribute(XAttribute node) { return node.Update(node.Name, node.Value); } protected virtual XObject VisitComment(XComment node) { return node.Update(node.Value); } protected virtual XObject VisitDocument(XDocument node) { return node.Update( node.Declaration, VisitAndConvert(node.Nodes()) ); } protected virtual XObject VisitElement(XElement node) { return node.Update( node.Name, VisitAndConvert(node.Attributes()), VisitAndConvert(node.Nodes()) ); } protected virtual XObject VisitDocumentType(XDocumentType node) { return node.Update( node.Name, node.PublicId, node.SystemId, node.InternalSubset ); } protected virtual XObject VisitProcessingInstruction(XProcessingInstruction node) { return node.Update( node.Target, node.Data ); } protected virtual XObject VisitText(XText node) { return node.Update(node.Value); } protected virtual XObject VisitCData(XCData node) { return node.Update(node.Value); } #region Implementation details internal InternalAccessor Accessor { get { return new InternalAccessor(this); } } internal class InternalAccessor { private XObjectVisitor visitor; internal InternalAccessor(XObjectVisitor visitor) { this.visitor = visitor; } internal XObject VisitAttribute(XAttribute node) { return visitor.VisitAttribute(node); } internal XObject VisitComment(XComment node) { return visitor.VisitComment(node); } internal XObject VisitDocument(XDocument node) { return visitor.VisitDocument(node); } internal XObject VisitElement(XElement node) { return visitor.VisitElement(node); } internal XObject VisitDocumentType(XDocumentType node) { return visitor.VisitDocumentType(node); } internal XObject VisitProcessingInstruction(XProcessingInstruction node) { return visitor.VisitProcessingInstruction(node); } internal XObject VisitText(XText node) { return visitor.VisitText(node); } internal XObject VisitCData(XCData node) { return visitor.VisitCData(node); } } #endregion } public static class XObjectVisitorExtensions { #region XObject.Accept "instance" method public static XObject Accept(this XObject node, XObjectVisitor visitor) { Validation.CheckNullReference(node); Validation.CheckArgumentNull(visitor, "visitor"); // yay, easy dynamic dispatch Acceptor acceptor = new Acceptor(node as dynamic); return acceptor.Accept(visitor); } private class Acceptor { public Acceptor(XAttribute node) : this(v => v.Accessor.VisitAttribute(node)) { } public Acceptor(XComment node) : this(v => v.Accessor.VisitComment(node)) { } public Acceptor(XDocument node) : this(v => v.Accessor.VisitDocument(node)) { } public Acceptor(XElement node) : this(v => v.Accessor.VisitElement(node)) { } public Acceptor(XDocumentType node) : this(v => v.Accessor.VisitDocumentType(node)) { } public Acceptor(XProcessingInstruction node) : this(v => v.Accessor.VisitProcessingInstruction(node)) { } public Acceptor(XText node) : this(v => v.Accessor.VisitText(node)) { } public Acceptor(XCData node) : this(v => v.Accessor.VisitCData(node)) { } private Func<XObjectVisitor, XObject> accept; private Acceptor(Func<XObjectVisitor, XObject> accept) { this.accept = accept; } public XObject Accept(XObjectVisitor visitor) { return accept(visitor); } } #endregion #region XObject.Update "instance" method public static XObject Update(this XAttribute node, XName name, string value) { Validation.CheckNullReference(node); Validation.CheckArgumentNull(name, "name"); Validation.CheckArgumentNull(value, "value"); return new XAttribute(name, value); } public static XObject Update(this XComment node, string value = null) { Validation.CheckNullReference(node); return new XComment(value); } public static XObject Update(this XDocument node, XDeclaration declaration = null, params object[] content) { Validation.CheckNullReference(node); return new XDocument(declaration, content); } public static XObject Update(this XElement node, XName name, params object[] content) { Validation.CheckNullReference(node); Validation.CheckArgumentNull(name, "name"); return new XElement(name, content); } public static XObject Update(this XDocumentType node, string name, string publicId = null, string systemId = null, string internalSubset = null) { Validation.CheckNullReference(node); Validation.CheckArgumentNull(name, "name"); return new XDocumentType(name, publicId, systemId, internalSubset); } public static XObject Update(this XProcessingInstruction node, string target, string data) { Validation.CheckNullReference(node); Validation.CheckArgumentNull(target, "target"); Validation.CheckArgumentNull(data, "data"); return new XProcessingInstruction(target, data); } public static XObject Update(this XText node, string value = null) { Validation.CheckNullReference(node); return new XText(value); } public static XObject Update(this XCData node, string value = null) { Validation.CheckNullReference(node); return new XCData(value); } #endregion } public static class Validation { public static void CheckNullReference<T>(T obj) where T : class { if (obj == null) throw new NullReferenceException(); } public static void CheckArgumentNull<T>(T obj, string paramName) where T : class { if (obj == null) throw new ArgumentNullException(paramName); } }

ps, esta implementación particular usa algunas características de .NET 4 para hacer que la implementación sea un poco más fácil / limpia (uso de argumentos dynamic y predeterminados). No debería ser demasiado difícil hacerlo compatible con .NET 3.5, incluso compatible con .NET 2.0.

Luego, para implementar el visitante, aquí hay uno generalizado que puede cambiar varios espacios de nombres (y el prefijo utilizado).

public class ChangeNamespaceVisitor : XObjectVisitor { private INamespaceMappingManager manager; public ChangeNamespaceVisitor(INamespaceMappingManager manager) { Validation.CheckArgumentNull(manager, "manager"); this.manager = manager; } protected INamespaceMappingManager Manager { get { return manager; } } private XName ChangeNamespace(XName name) { var mapping = Manager.GetMapping(name.Namespace); return mapping.ChangeNamespace(name); } private XObject ChangeNamespaceDeclaration(XAttribute node) { var mapping = Manager.GetMapping(node.Value); return mapping.ChangeNamespaceDeclaration(node); } protected override XObject VisitAttribute(XAttribute node) { if (node.IsNamespaceDeclaration) return ChangeNamespaceDeclaration(node); return node.Update(ChangeNamespace(node.Name), node.Value); } protected override XObject VisitElement(XElement node) { return node.Update( ChangeNamespace(node.Name), VisitAndConvert(node.Attributes()), VisitAndConvert(node.Nodes()) ); } } // and all the gory implementation details public class NamespaceMappingManager : INamespaceMappingManager { private Dictionary<XNamespace, INamespaceMapping> namespaces = new Dictionary<XNamespace, INamespaceMapping>(); public NamespaceMappingManager Add(XNamespace fromNs, XNamespace toNs, string toPrefix = null) { var item = new NamespaceMapping(fromNs, toNs, toPrefix); namespaces.Add(item.FromNs, item); return this; } public INamespaceMapping GetMapping(XNamespace fromNs) { INamespaceMapping mapping; if (!namespaces.TryGetValue(fromNs, out mapping)) mapping = new NullMapping(); return mapping; } private class NullMapping : INamespaceMapping { public XName ChangeNamespace(XName name) { return name; } public XObject ChangeNamespaceDeclaration(XAttribute node) { return node.Update(node.Name, node.Value); } } private class NamespaceMapping : INamespaceMapping { private XNamespace fromNs; private XNamespace toNs; private string toPrefix; public NamespaceMapping(XNamespace fromNs, XNamespace toNs, string toPrefix = null) { this.fromNs = fromNs ?? ""; this.toNs = toNs ?? ""; this.toPrefix = toPrefix; } public XNamespace FromNs { get { return fromNs; } } public XNamespace ToNs { get { return toNs; } } public string ToPrefix { get { return toPrefix; } } public XName ChangeNamespace(XName name) { return name.Namespace == fromNs ? toNs + name.LocalName : name; } public XObject ChangeNamespaceDeclaration(XAttribute node) { if (node.Value == fromNs.NamespaceName) { if (toNs == XNamespace.None) return null; var xmlns = !String.IsNullOrWhiteSpace(toPrefix) ? (XNamespace.Xmlns + toPrefix) : node.Name; return node.Update(xmlns, toNs.NamespaceName); } return node.Update(node.Name, node.Value); } } } public interface INamespaceMappingManager { INamespaceMapping GetMapping(XNamespace fromNs); } public interface INamespaceMapping { XName ChangeNamespace(XName name); XObject ChangeNamespaceDeclaration(XAttribute node); }

Y un pequeño método de ayuda para hacer rodar la pelota:

T ChangeNamespace<T>(T node, XNamespace fromNs, XNamespace toNs, string toPrefix = null) where T : XObject { return node.Accept( new ChangeNamespaceVisitor( new NamespaceMappingManager() .Add(fromNs, toNs, toPrefix) ) ) as T; }

Luego, para eliminar un espacio de nombre, puedes llamarlo así:

var doc = ChangeNamespace(XDocument.Load(pathToXml), fromNs: "http://schema.peters.com/doc_353/1/Types", toNs: null);

Usando este visitante, puede escribir un INamespaceMappingManager para eliminar todos los espacios de nombres.

T RemoveAllNamespaces<T>(T node) where T : XObject { return node.Accept( new ChangeNamespaceVisitor(new RemoveNamespaceMappingManager()) ) as T; } public class RemoveNamespaceMappingManager : INamespaceMappingManager { public INamespaceMapping GetMapping(XNamespace fromNs) { return new RemoveNamespaceMapping(); } private class RemoveNamespaceMapping : INamespaceMapping { public XName ChangeNamespace(XName name) { return name.LocalName; } public XObject ChangeNamespaceDeclaration(XAttribute node) { return null; } } }


Solución simple que realmente cambia el nombre de los elementos in situ, no crea una copia, y hace un buen trabajo reemplazando los atributos.

public void RemoveAllNamespaces(ref XElement value) { List<XAttribute> attributesToRemove = new List<XAttribute>(); foreach (void e_loopVariable in value.DescendantsAndSelf) { e = e_loopVariable; if (e.Name.Namespace != XNamespace.None) { e.Name = e.Name.LocalName; } foreach (void a_loopVariable in e.Attributes) { a = a_loopVariable; if (a.IsNamespaceDeclaration) { //do not keep it at all attributesToRemove.Add(a); } else if (a.Name.Namespace != XNamespace.None) { e.SetAttributeValue(a.Name.LocalName, a.Value); attributesToRemove.Add(a); } } } foreach (void a_loopVariable in attributesToRemove) { a = a_loopVariable; a.Remove(); } }

Nota: esto no siempre conserva el orden original de los atributos, pero estoy seguro de que podrías cambiarlo para hacerlo fácilmente si es importante para ti.

También tenga en cuenta que esto también podría arrojar una excepción, si tiene atributos de XElement que son únicos con el espacio de nombres, como:

<root xmlns:ns1="a" xmlns:ns2="b"> <elem ns1:dupAttrib="" ns2:dupAttrib="" /> </root>

which really seems like an inherent problem. But since the question indicated outputing a String, not an XElement, in this case you could have a solution that would output a valid String that was an invalid XElement.

I also liked jocull''s answer using a custom XmlWriter, but when I tried it, it did not work for me. Although it all looks correct, I couldn''t tell if the XmlNoNamespaceWriter class had any effect at all; it definitely was not removing the namespaces as I wanted it to.


Y esta es la solución perfecta que también eliminará los elementos XSI. (Si elimina los xmlns y no elimina XSI, .Net grita a usted ...)

string xml = node.OuterXml; //Regex below finds strings that start with xmlns, may or may not have :and some text, then continue with = //and ", have a streach of text that does not contain quotes and end with ". similar, will happen to an attribute // that starts with xsi. string strXMLPattern = @"xmlns(:/w+)?=""([^""]+)""|xsi(:/w+)?=""([^""]+)"""; xml = Regex.Replace(xml, strXMLPattern, "");


la respuesta obligatoria usando LINQ:

static XElement stripNS(XElement root) { return new XElement( root.Name.LocalName, root.HasElements ? root.Elements().Select(el => stripNS(el)) : (object)root.Value ); } static void Main() { var xml = XElement.Parse(@"<?xml version=""1.0"" encoding=""utf-16""?> <ArrayOfInserts xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema""> <insert> <offer xmlns=""http://schema.peters.com/doc_353/1/Types"">0174587</offer> <type2 xmlns=""http://schema.peters.com/doc_353/1/Types"">014717</type2> <supplier xmlns=""http://schema.peters.com/doc_353/1/Types"">019172</supplier> <id_frame xmlns=""http://schema.peters.com/doc_353/1/Types"" /> <type3 xmlns=""http://schema.peters.com/doc_353/1/Types""> <type2 /> <main>false</main> </type3> <status xmlns=""http://schema.peters.com/doc_353/1/Types"">Some state</status> </insert> </ArrayOfInserts>"); Console.WriteLine(stripNS(xml)); }


Adding my that also cleans out the name of nodes that have namespace prefixes:

public static string RemoveAllNamespaces(XElement element) { string tex = element.ToString(); var nsitems = element.DescendantsAndSelf().Select(n => n.ToString().Split('' '', ''>'')[0].Split(''<'')[1]).Where(n => n.Contains(":")).DistinctBy(n => n).ToArray(); //Namespace prefix on nodes: <a:nodename/> tex = nsitems.Aggregate(tex, (current, nsnode) => current.Replace("<"+nsnode + "", "<" + nsnode.Split('':'')[1] + "")); tex = nsitems.Aggregate(tex, (current, nsnode) => current.Replace("</" + nsnode + "", "</" + nsnode.Split('':'')[1] + "")); //Namespace attribs var items = element.DescendantsAndSelf().SelectMany(d => d.Attributes().Where(a => a.IsNamespaceDeclaration || a.ToString().Contains(":"))).DistinctBy(o => o.Value); tex = items.Aggregate(tex, (current, xAttribute) => current.Replace(xAttribute.ToString(), "")); return tex; }


After much searching for a solution to this very issue, this particular page seemed to have the most beef...however, nothing quite fit exactly, so I took the old-fashioned way and just parsed the stuff out I wanted out. Espero que esto ayude a alguien. (Note: this also removes the SOAP or similar envelope stuff.)

public static string RemoveNamespaces(string psXml) { // // parse through the passed XML, and remove any and all namespace references...also // removes soap envelope/header(s)/body, or any other references via ":" entities, // leaving all data intact // string xsXml = "", xsCurrQtChr = ""; int xiPos = 0, xiLastPos = psXml.Length - 1; bool xbInNode = false; while (xiPos <= xiLastPos) { string xsCurrChr = psXml.Substring(xiPos, 1); xiPos++; if (xbInNode) { if (xsCurrChr == ":") { // soap envelope or body (or some such) // we''ll strip these node wrappers completely // need to first strip the beginning of it off (i.e. "<soap" or "<s") int xi = xsXml.Length; string xsChr = ""; do { xi--; xsChr = xsXml.Substring(xi, 1); xsXml = xsXml.Substring(0, xi); } while (xsChr != "<"); // next, find end of node string xsQt = ""; do { xiPos++; if (xiPos <= xiLastPos) { xsChr = psXml.Substring(xiPos, 1); if (xsQt.Length == 0) { if (xsChr == "''" || xsChr == "/"") { xsQt = xsChr; } } else { if (xsChr == xsQt) { xsQt = ""; // end of quote } else { if (xsChr == ">") xsChr = "x"; // stay in loop...this is not end of node } } } } while (xsChr != ">" && xiPos <= xiLastPos); xiPos++; // skip over closing ">" xbInNode = false; } else { if (xsCurrChr == ">") { xbInNode = false; xsXml += xsCurrChr; } else { if (xsCurrChr == " " || xsCurrChr == "/t") { // potential namespace...let''s check...next character must be "/" // or more white space, and if not, skip until we find such string xsChr = ""; int xiOrgLen = xsXml.Length; xsXml += xsCurrChr; do { if (xiPos <= xiLastPos) { xsChr = psXml.Substring(xiPos, 1); xiPos++; if (xsChr == " " || xsChr == "/r" || xsChr == "/n" || xsChr == "/t") { // carry on..white space xsXml += xsChr; } else { if (xsChr == "/" || xsChr == ">") { xsXml += xsChr; } else { // namespace! - get rid of it xsXml = xsXml.Substring(0, xiOrgLen - 0); // first, truncate any added whitespace // next, peek forward until we find "/" or ">" string xsQt = ""; do { if (xiPos <= xiLastPos) { xsChr = psXml.Substring(xiPos, 1); xiPos++; if (xsQt.Length > 0) { if (xsChr == xsQt) xsQt = ""; else xsChr = "x"; } else { if (xsChr == "''" || xsChr == "/"") xsQt = xsChr; } } } while (xsChr != ">" && xsChr != "/" && xiPos <= xiLastPos); if (xsChr == ">" || xsChr == "/") xsXml += xsChr; xbInNode = false; } } } } while (xsChr != ">" && xsChr != "/" && xiPos <= xiLastPos); } else { xsXml += xsCurrChr; } } } } else { // // if not currently inside a node, then we are in a value (or about to enter a new node) // xsXml += xsCurrChr; if (xsCurrQtChr.Length == 0) { if (xsCurrChr == "<") { xbInNode = true; } } else { // // currently inside a quoted string // if (xsCurrQtChr == xsCurrChr) { // finishing quoted string xsCurrQtChr = ""; } } } } return (xsXml); }


Aquí hay una solución basada en expresiones regulares para este problema ...

private XmlDocument RemoveNS(XmlDocument doc) { var xml = doc.OuterXml; var newxml = Regex.Replace(xml, @"xmlns[:xsi|:xsd]*="".*?""",""); var newdoc = new XmlDocument(); newdoc.LoadXml(newxml); return newdoc; }


Bit late to the party on this one but here''s what I used recently:

var doc = XDocument.Parse(xmlString); doc.Root.DescendantNodesAndSelf().OfType<XElement>().Attributes().Where(att => att.IsNamespaceDeclaration).Remove();

(taken from this MSDN Thread )


Here''s are Regex Replace one liner:

public static string RemoveNamespaces(this string xml) { return Regex.Replace(xml, "((?<=<|<///)|(?<= ))[A-Za-z0-9]+:| xmlns(:[A-Za-z0-9]+)?=/".*?/"", ""); }

Here''s a sample: https://regex101.com/r/fopydN/6

Warning:there might be edge cases!


I tried the first few solutions and didn''t work for me. Mainly the problem with attributes being removed like the other have already mentioned. I would say my approach is very similar to Jimmy by using the XElement constructors that taking object as parameters.

public static XElement RemoveAllNamespaces(this XElement element) { return new XElement(element.Name.LocalName, element.HasAttributes ? element.Attributes().Select(a => new XAttribute(a.Name.LocalName, a.Value)) : null, element.HasElements ? element.Elements().Select(e => RemoveAllNamespaces(e)) : null, element.Value); }


Without recreating whole node hierarchy:

private static void RemoveDefNamespace(XElement element) { var defNamespase = element.Attribute("xmlns"); if (defNamespase != null) defNamespase.Remove(); element.Name = element.Name.LocalName; foreach (var child in element.Elements()) { RemoveDefNamespace(child); } }


my answer, string-manipulation-based,
lite-most code,

public static string hilangkanNamespace(string instrXML) { char chrOpeningTag = ''<''; char chrClosingTag = ''>''; char chrSpasi = '' ''; int intStartIndex = 0; do { int intIndexKu = instrXML.IndexOf(chrOpeningTag, intStartIndex); if (intIndexKu < 0) break; //kalau dah ga ketemu keluar int intStart = instrXML.IndexOfAny(new char[] { chrSpasi, chrClosingTag }, intIndexKu + 1); //mana yang ketemu duluan if (intStart < 0) break; //kalau dah ga ketemu keluar int intStop = instrXML.IndexOf(chrClosingTag, intStart); if (intStop < 0) break; //kalau dah ga ketemu keluar else intStop--; //exclude si closingTag int intLengthToStrip = intStop - intStart + 1; instrXML = instrXML.Remove(intStart, intLengthToStrip); intStartIndex = intStart; } while (true); return instrXML; }


user892217''s answer is almost correct. It won''t compile as is, so needs a slight correction to the recursive call:

private static XElement RemoveAllNamespaces(XElement xmlDocument) { XElement xElement; if (!xmlDocument.HasElements) { xElement = new XElement(xmlDocument.Name.LocalName) { Value = xmlDocument.Value }; } else { xElement = new XElement(xmlDocument.Name.LocalName, xmlDocument.Elements().Select(x => RemoveAllNamespaces(x))); } foreach (var attribute in xmlDocument.Attributes()) { if (!attribute.IsNamespaceDeclaration) { xElement.Add(attribute); } } return xElement; }


Creo que esta es la respuesta más corta (pero para constuctions como, tendrás otra discusión, también tengo una expresión regular para convertir "<bcm:info></bcm:info>"a " <info></info>" pero no fue optimizada, si alguien me pregunta, la compartiré. Entonces, mi solución es:

public string RemoveAllNamespaces(string xmlDocument) { return Regex.Replace(xmlDocument, @"/sxmlns(/u003A/w+)?/u003D/u0022.+/u0022", " "); }