9

Before posting this question I have tried all other solution on stack, but with no success.

I am unable to remove empty xmlns attribute from XElement using C#, I have tried the following Codes.

XElement.Attributes().Where(a => a.IsNamespaceDeclaration).Remove();

Another one which postted here

foreach (var attr in objXMl.Descendants().Attributes())
{
    var elem = attr.Parent;
    attr.Remove();
    elem.Add(new XAttribute(attr.Name.LocalName, attr.Value));
}
Community
  • 1
  • 1
naim shaikh
  • 1,103
  • 2
  • 9
  • 20

4 Answers4

22

Image This is you xml file

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

This is you expect

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

I think the code below is what you want. You need to put each element into the right namespace, and remove any xmlns='' attributes for the affected elements. The latter part is required as otherwise LINQ to XML basically tries to leave you with an element of

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

Here's the code:

using System;
using System.Xml.Linq;

class Test
{
    static void Main()
    {
        XDocument doc = XDocument.Load("test.xml");
        foreach (var node in doc.Root.Descendants())
        {
            // If we have an empty namespace...
            if (node.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(...)
    }
}
Gehan Fernando
  • 1,221
  • 13
  • 24
  • in node.Name line, check node parent for null if (node.Parent != null) node.Name = node.Parent.Name.Namespace + node.Name.LocalName; – Alex Jun 15 '20 at 06:16
  • The `node.Attributes("xmlns").Remove();` is redundant. all you need is to set the new `Name` of the `XElement`. – itsho Feb 01 '21 at 11:05
5

If you add the namespace of the parent element to the element then the empty namespace tag disappears, as it isn't required because the element is in the same namespace.

1

here's a simpler way to do this. I believe it happens when you create separate xml segments and then join them to your document.

xDoc.Root.SaveDocument(savePath);
private static void SaveDocument(this XElement doc, string filePath)
{
    foreach (var node in doc.Descendants())
    {
        if (node.Name.NamespaceName == "")
        {
            node.Name = ns + node.Name.LocalName;
        }
    }
    using (var xw = XmlWriter.Create(filePath, new XmlWriterSettings
    {
        //OmitXmlDeclaration = true,
        //Indent = true,
        NamespaceHandling = NamespaceHandling.OmitDuplicates
    }))
    {
        doc.Save(xw);
    }
}   
0

Did you try to get Xelement.Attribute by value to see if the element is the "xmlns" before removing.

Xelement.Attribute("xmlns").Value 
NTMS
  • 816
  • 7
  • 22