How to Remove All Namespaces from Xml With C#

How to remove all namespaces from XML with C#?

Well, here is the final answer. I have used great Jimmy idea (which unfortunately is not complete itself) and complete recursion function to work properly.

Based on interface:

string RemoveAllNamespaces(string xmlDocument);

I represent here final clean and universal C# solution for removing XML namespaces:

//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)));
}

It's working 100%, but I have not tested it much so it may not cover some special cases... But it is good base to start.

Remove q1 and all namespaces from xml

The simplest way is to 'post-process' the XML:

var doc = XDocument.Parse(xml);

doc.Descendants().Attributes().Where(a => a.IsNamespaceDeclaration).Remove();

foreach (var element in doc.Descendants())
{
element.Name = element.Name.LocalName;
}

var xmlWithoutNamespaces = doc.ToString();

The other option (as you can't amend the source class XML attributes) is to implement a decorator for XmlWriter that ignores all namespaces, but it's quite a large class so there'd be a lot of boilerplate delegation.

Linq to Xml : Remove namespace

As stated here

Based on interface:

string RemoveAllNamespaces(string xmlDocument);

I represent here final clean and universal C# solution for removing
XML namespaces:

//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)));
}

Above solution still have two flase

  • It ignores attributes
  • It doesn't work with "mixed mode" elements

Here is another solution:

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

Sample code here.

C# - How to remove xmlns from XElement

I'd like to expand upon the existing answers. Specifically, I'd like to refer to a common use-case for removing namespaces from an XElement, which is: to be able to use Linq queries in the usual way.

When a tag contains a namespace, one has to use this namespace as an XNamespace on every Linq query (as explained in this answer), so that with the OP's xml, it would be:

XNamespace ns = "http://www.blablabla.com/bla";
var element = xelement.Descendants(ns + "retEvent")).Single();

But usually, we don't want to use this namespace every time. So we need to remove it.

Now, @octaviocc's suggestion does remove the namespace attribute from a given element. However, the element name still contains that namespace, so that the usual Linq queries won't work.

Console.WriteLine(xelement.Attributes().Count()); // prints 1
xelement.Attributes().Where( e => e.IsNamespaceDeclaration).Remove();
Console.WriteLine(xelement.Attributes().Count()); // prints 0
Console.WriteLine(xelement.Name.Namespace); // prints "http://www.blablabla.com/bla"
XNamespace ns = "http://www.blablabla.com/bla";
var element1 = xelement.Descendants(ns + "retEvent")).SingleOrDefault(); // works
var element2 = xelement.Descendants("retEvent")).SingleOrDefault(); // returns null

Thus, we need to use @Sam Shiles suggestion, but it can be simplified (no need for recursion):

private static void RemoveAllNamespaces(XElement xElement)
{
foreach (var node in xElement.DescendantsAndSelf())
{
node.Name = node.Name.LocalName;
}
}

And if one needs to use an XDocument:

private static void RemoveAllNamespaces(XDocument xDoc)
{
foreach (var node in xDoc.Root.DescendantsAndSelf())
{
node.Name = node.Name.LocalName;
}
}

And now it works:

var element = xelement.Descendants("retEvent")).SingleOrDefault();

How to strip namespaces from Xml Document

Your problem is that you're removing the namespace prefix from the root element, but it's still being used to qualify the attributes themselves in the rest of the document. You want to strip namespaces out of the entire document first.

public static class XmlExtensions
{
public static void StripNamespace(this XDocument document)
{
if (document.Root == null) return;

foreach (var element in document.Root.DescendantsAndSelf())
{
element.Name = element.Name.LocalName;
element.ReplaceAttributes(GetAttributesWithoutNamespace(element));
}
}

static IEnumerable<XAttribute> GetAttributesWithoutNamespace(XElement xElement)
{
return xElement.Attributes()
.Where(x => !x.IsNamespaceDeclaration)
.Select(x => new XAttribute(x.Name.LocalName, x.Value));
}
}

Then simply:

XDocument xDoc = XDocument.Parse(xml);
xDoc.StripNamespace();
xDoc.Root.Add(new XAttribute(XNamespace.Xmlns + "xsi", "http://www.w3.org/2001/XMLSchema-instance\\"));
xDoc.Root.Add(new XAttribute(XNamespace.Xmlns + "xsd", "http://www.w3.org/2001/XMLSchema\\"));

This produces the XML you were after.

Remove all nodes in a specified namespace from XML

Iterating through elements then through attributes seems not too hard to read :

var xml = @"<?xml version='1.0' encoding='UTF-8'?>
<root xmlns:test='urn:my-test-urn'>
<Item name='Item one'>
<test:AlternativeName>Another name</test:AlternativeName>
<Price test:Currency='GBP'>124.00</Price>
</Item>
</root>";
var doc = XDocument.Parse(xml);
XNamespace test = "urn:my-test-urn";

//get all elements in specific namespace and remove
doc.Descendants()
.Where(o => o.Name.Namespace == test)
.Remove();
//get all attributes in specific namespace and remove
doc.Descendants()
.Attributes()
.Where(o => o.Name.Namespace == test)
.Remove();

//print result
Console.WriteLine(doc.ToString());

output :

<root xmlns:test="urn:my-test-urn">
<Item name="Item one">
<Price>124.00</Price>
</Item>
</root>


Related Topics



Leave a reply



Submit