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.

Answer from Peter Stegnar on Stack Overflow
🌐
Medium
medium.com › @mansoorsyed05 › how-to-remove-namespaces-in-xml-here-is-how-4de5a1a4e137
How to remove namespaces in XML? Here is how!! | by Mansoor Basha Syed | Medium
March 20, 2022 - This simple article will help you to remove them out of your way. I have used “ xml.etree.ElementTree” package in this code, which is already an inbuilt feature of python., So no need to install any external packages ... # Reading XML file with open("sample.xml", "r") as file: content = file.read() #Finding the root of XMLroot = ET.ElementTree(ET.fromstring(content)).getroot()# Iterating through child tags for elem in tree.iter(): tag_elements = elem.tag.split("}") # Removing name spaces and attributes elem.tag = tag_elements[1] elem.attrib.clear() updated_data = ET.tostring(root) print(tree_data)
🌐
Myxml
myxml.in › xml-utils.html
Online XML Utilities - Remove, Optimize namespaces. Prettify, Sort XML and much more
Remove all namespaces from a xml. Optimize or remove duplicate namespace prefixes in a xml. Format xml with default namespace prefix. Prettify a xml. Sort or order all xml elements by element name in alphabetical order. Sort xml repeating element by either element or attribute value.
Discussions

How can i remove namespace prefix without removing the xmlns tag?
Next time please don't post the XSLT as a screenshot, this makes it harder to play with it. More on reddit.com
🌐 r/xml
5
1
June 20, 2024
Remove all namespace attributes from xml using xmlstarlet - Unix & Linux Stack Exchange
1 I want to add a namespace prefix to the tags of the default name space of an XML document from the shell · 5 Use xmlstarlet to remove an entire element that matches an attribute value? More on unix.stackexchange.com
🌐 unix.stackexchange.com
How to remove namespaces from XML using XSLT - Stack Overflow
See similar questions with these tags. ... 0 XSLT: copy all the children of without the m: namespace without having to create a template for each element · 0 Extracting child nodes from a single parent using XSLT and reformatting · 19 XSL - How to remove unused namespaces from source xml? More on stackoverflow.com
🌐 stackoverflow.com
c# - How to remove 2 parent namespace tags from XML document - Stack Overflow
I have the following XML document, but I need to remove the first two elements (and keep all the children). I can't seem to do this using XPath because they are namespaces? I don't really understan... More on stackoverflow.com
🌐 stackoverflow.com
Top answer
1 of 16
122

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.

2 of 16
68

The tagged most useful answer has two flaws:

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

Here is my take on this:

 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.

🌐
Reddit
reddit.com › r/xml › how can i remove namespace prefix without removing the xmlns tag?
r/xml on Reddit: How can i remove namespace prefix without removing the xmlns tag?
June 20, 2024 -

I am using this xslt but it does not remove the prefix after xmlns:

Sample input:

<root> <ns1:AppHdr xmlns:ns1="http://example.com/ns1"> <ns1:sender>Sender1</ns1:sender> <ns1:receiver>Receiver1</ns1:receiver> </ns1:AppHdr> <ns2:Document xmlns:ns2="http://example.com/ns2"> <ns2:title>Document Title</ns2:title> <ns2:author>Author Name</ns2:author> </ns2:Document> </root>

Expected output:

<root> <AppHdr xmlns="http://example.com/ns1"> <sender>Sender1</sender> <receiver>Receiver1</receiver> </AppHdr> <Document xmlns="http://example.com/ns2"> <title>Document Title</title> <author>Author Name</author> </Document> </root>

Output with current xslt:

<root> <AppHdr xmlns:ns1="http://example.com/ns1"> <sender>Sender1</sender> <receiver>Receiver1</receiver> </AppHdr> <Document xmlns:ns2="http://example.com/ns2"> <title>Document Title</title> <author>Author Name</author> </Document> </root>

🌐
Roy Tutorials
roytuts.com › home › java › how to remove namespace from xml using xslt
How To Remove Namespace from XML Using XSLT - Roy Tutorials
October 30, 2023 - Removing Namespace In this tutorial I will show you how to remove namespace from XML using XSLT. Removing namespaces from an XML document is not
Find elsewhere
🌐
Microsoft
social.msdn.microsoft.com › Forums › vstudio › en-US › 8e15a247-92fd-46de-b3be-90b3d4d95a7c › how-to-remove-xml-namespace-prefixes-in-c
How to remove xml namespace prefixes in c# | Microsoft Learn
November 8, 2021 - Here's how to remove the namespaces themselves (from code posted here). var doc = XDocument.Load("Test.xml"); var namespaces = from a in doc.Descendants().Attributes() where a.IsNamespaceDeclaration && a.Name != "xsi" select a; namespaces.Remove(); doc.Save("Test_New.xml");
Top answer
1 of 2
2

I have found a couple of XSLT solutions to do this, both of which can conveniently be processed with xmlstarlet:

  1. How to remove the namespace and its prefixes in an XML file using XSLT? - IBM
  2. XSLT: Remove namespace prefix from elements - StackOverflow

In my worked example below, I've used the IBM code and saved it into the file xslt_ibm:

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <!-- https://www.ibm.com/support/pages/how-remove-namespace-and-its-prefixes-xml-file-using-xslt -->
  <xsl:output method="xml" indent="yes"/>
  <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>

If you consider your XML file to be saved in the file file.xml then this command will rename each element and attribute out of its namespace:

xmlstarlet transform xslt_ibm file.xml

Input (file.xml)

<md:EntityDescriptor xmlns="urn:_" xmlns:md="_"></md:EntityDescriptor>

Output

<?xml version="1.0"?>
<EntityDescriptor/>
2 of 2
0

Using Andrey Kislyuk's xq, an XML-parsing wrapper around jq (installed together with yq):

xq -x 'walk(del( .["@xmlns"]?, .["@xmlns:md"]? ))' file

This walks all nodes in the XML document structure and deletes all xmlns and xmlns:md attributes wherever these are found.

Given some input document,

<?xml version="1.0"?>
<root test="val">
  <md:EntityDescriptor xmlns="urn:_" xmlns:md="_"/>
</root>

... this would output

<root test="val">
  <md:EntityDescriptor></md:EntityDescriptor>
</root>

You get in-place editing with the --in-place or -i option.

Top answer
1 of 3
40

Your XSLT removes attributes also, because you don't have a template that would copy them. <xsl:template match="*"> matches only elements, not attributes (or text, comments or processing instructions).

Below is a stylesheet that removes all namespace definitions from the processed document but copies all other nodes and values: elements, attributes, comments, text and processing instructions. Please pay attention to 2 things

  1. Copying the attributes as such is not enough to remove all namespaces. Also an attribute can belong to a namespace, even when the containing element doesn't belong to a namespace. Therefore also attributes need to be created, like elements. Creating attributes is done with <xsl:attribute> element.
  2. A valid XML document cannot contain an element that has two or more attributes with same expanded name but elements can contain multiple attributes with same local name if the attributes have different namespaces. This means that removing the namespace prefix from an attribute name will cause dataloss if there is an element that has at leas two attributes with same local name. Other one of these attributes will be removed (or overwritten).

...and the code:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output indent="yes" method="xml" encoding="utf-8" omit-xml-declaration="yes"/>

    <!-- Stylesheet to remove all namespaces from a document -->
    <!-- NOTE: this will lead to attribute name clash, if an element contains
        two attributes with same local name but different namespace prefix -->
    <!-- Nodes that cannot have a namespace are copied as such -->

    <!-- template to copy elements -->
    <xsl:template match="*">
        <xsl:element name="{local-name()}">
            <xsl:apply-templates select="@* | node()"/>
        </xsl:element>
    </xsl:template>

    <!-- template to copy attributes -->
    <xsl:template match="@*">
        <xsl:attribute name="{local-name()}">
            <xsl:value-of select="."/>
        </xsl:attribute>
    </xsl:template>

    <!-- template to copy the rest of the nodes -->
    <xsl:template match="comment() | text() | processing-instruction()">
        <xsl:copy/>
    </xsl:template>

</xsl:stylesheet>

You could also use <xsl:template match="node()"> instead of that last template but then you should use priority attribute to prevent elements matching to this template.

2 of 3
1

How can I include the attributes there?

Just append this template to the one you already have:

<xsl:template match="@*">
    <xsl:copy/>
</xsl:template>
🌐
IBM
ibm.com › docs › en › i › 7.4.0
Example: Using XSLT to remove namespaces
XML documents you receive might contain unneeded or incorrect namespace information. You can use XSLT style sheets to remove or manipulate the namespace information in the documents.
Top answer
1 of 3
2

Try this

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string xml =
                "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>" +
                "<mgns1:PlaceXmlMessage xmlns:mgns1=\"http://www.testing.com/\">" +
                    "<mgns1:xmlDocument>" +
                        "<HubChangeRequest version=\"1.0\">" +
                            "<TransactionReference>" +
                                "<AuthenticationID>TestSUPPLIERS</AuthenticationID>" +
                                "<AuthenticationKey>hidden</AuthenticationKey>" +
                                "<TransactionNumber>hidden</TransactionNumber>" +
                            "</TransactionReference>" +
                            "<MessageNumber>hidden</MessageNumber>" +
                            "<MessageCreatedDate>2016-03-01T12:31:31</MessageCreatedDate>" +
                            "<ReferenceNumber>ABC123456789</ReferenceNumber>" +
                            "<ProductDetails>" +
                                "<StockItem LineReference=\"123456/1\">" +
                                    "<NewStatus>Despatched</NewStatus>" +
                                    "<DespatchReference>3 PARCEL LINE</DespatchReference>" +
                                "</StockItem>" +
                                "<StockItem LineReference=\"123345/2\">" +
                                    "<NewStatus>Despatched</NewStatus>" +
                                    "<DespatchReference>3 PARCEL LINE</DespatchReference>" +
                                "</StockItem>" +
                            "</ProductDetails>" +
                        "</HubChangeRequest>" +
                    "</mgns1:xmlDocument>" +
                "</mgns1:PlaceXmlMessage>";

            XDocument doc = XDocument.Parse(xml);

            XElement placeXmlMessage = (XElement)doc.FirstNode;
            XElement secondNode = placeXmlMessage.Elements().FirstOrDefault();
            XElement hubChangeRequest = secondNode.Elements().FirstOrDefault();
            placeXmlMessage.ReplaceWith(hubChangeRequest);
        }
    }
}
2 of 3
1

You can use an XSLT transformation to get your input into the right output shape.

The following code transforms your input xml, assuming it lives in a string variable caled input, to an MemoryStream.

Transform input via XSLT to stream

// Create an XSLT Transformer
var xslt = new XslCompiledTransform();
xslt.Load("copydoc.xslt");

var settings = new XmlWriterSettings
{
    Encoding = new UTF8Encoding(false) // NO BOM
};

// open all streams for reading and writing
using (var ms = new MemoryStream())
{
    using (var xw = XmlWriter.Create(ms, settings))
    {
        // input is the string with the xml input
        using (var sr = new StringReader(input))
        using (var xr = XmlReader.Create(sr))
        {
            xslt.Transform(xr, xw);
            // the memorystream now has the result
        }
    }

    Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));
}

Copydoc.xslt

The Xslt file is fairly simple and uses two templates and a strategic apply-template to get the childnode under your <mgsn1:xmlDocument> node:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:msxsl="urn:schemas-microsoft-com:xslt" 
                xmlns:mgns1="http://www.testing.com/"
                exclude-result-prefixes="msxsl mgns1 "
>
    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="/">
      <!-- select the child node of xmlDocument-->
      <xsl:apply-templates select="mgns1:PlaceXmlMessage/mgns1:xmlDocument/child::*" />
    </xsl:template>

    <!-- match each element -->
    <xsl:template match="*">
      <!-- make sure to get rid of the namespaces-->
        <xsl:element name="{local-name(.)}">
        <!-- be explicit about copying attributes -->
        <xsl:apply-templates select="@*" />
        <!-- copy childs-->
            <xsl:apply-templates/>
        </xsl:element>
    </xsl:template>

    <!-- handle attributes -->
    <xsl:template match="@*">
        <xsl:copy/>
    </xsl:template>

</xsl:stylesheet>

If you add the file copydoc.xslt to your project don't forget to set the projectfile property Copy to output directory to copy always otherwise the xslt file will not be found.

🌐
Ask TOM
asktom.oracle.com › ords › f
XML file removing namespaces in attributes - Ask TOM
XML file removing namespaces in attributes Hello Tom & Team,Greetings to All of you!!!My query is in continuation w.r.t to an earlier question asked in the forum.'removing attribute from very large xml' date October 04, 2019 - 12:10 pm UTC.In this you have mentioned how to remove namespaces ...
🌐
Rdrr.io
rdrr.io › cran › XML › man › xmlCleanNamespaces.html
xmlCleanNamespaces: Remove redundant namespaces on an XML document in XML: Tools for Parsing and Generating XML Within R and S-Plus
April 4, 2025 - This is a convenience function that removes redundant repeated namespace definitions in an XML node. It removes namespace definitions in nodes where an ancestor node also has that definition.
Top answer
1 of 3
3

@Markus Freitag To override the behaviour of XmlSerializer you need XmlWriterSettings for override or remove XML declaration and XmlSerializerNamespaces for override namespace:

public static string ToXML(this T obj)  
{  
 // Remove Declaration  
 var settings = new XmlWriterSettings  
        {  
             Indent = true,  
             OmitXmlDeclaration = true  
        };  
  
 // Remove Namespace  
    var ns = new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty });  
  
    using (var stream = new StringWriter())  
    using (var writer = XmlWriter.Create(stream, settings))  
    {  
        var serializer = new XmlSerializer(typeof(T));  
        serializer.Serialize(writer, obj, ns);  
        return stream.ToString();  
    }  
}  

See full example here.

2 of 3
1

The most natural and easy way to implement it is via XSLT.
Please find below an example of it.

The XSLT is generic. It will remove (1) XML prolog declaration, and (2) any namespace(s) from any XML file.

Input XML



   
      
   

XSLT



 

 
 
 
 
 

 
 
 
 
 

 
 
 
 
 

Output XML


 
 
 

c# to launch XSLT transformation

void Main()
{
   const string SOURCEXMLFILE = @"e:\Temp\UniversalShipment.xml";
   const string XSLTFILE = @"e:\Temp\RemoveNamespaces.xslt";
   const string OUTPUTXMLFILE = @"e:\temp\UniversalShipment_output.xml";

   try
   {
      XsltArgumentList xslArg = new XsltArgumentList();

      using (XmlReader src = XmlReader.Create(SOURCEXMLFILE))
      {
         XslCompiledTransform xslt = new XslCompiledTransform();
         xslt.Load(XSLTFILE, new XsltSettings(true, true), new XmlUrlResolver());

         XmlWriterSettings settings = xslt.OutputSettings.Clone();
         settings.IndentChars = "\t";
         // to remove BOM
         settings.Encoding = new UTF8Encoding(false);

         using (XmlWriter result = XmlWriter.Create(OUTPUTXMLFILE, settings))
         {
            xslt.Transform(src, xslArg, result, new XmlUrlResolver());
            result.Close();
         }
      }
      Console.WriteLine("File '{0}' has been generated.", OUTPUTXMLFILE);
   }
   catch (Exception ex)
   {
      Console.WriteLine(ex.Message);
   }
}
🌐
W3Schools
w3schools.com › xml › met_element_removeattributens.asp
XML DOM removeAttributeNS() Method
var xhttp = new XMLHttpRequest(); ...").innerHTML += "<br>Attribute Found: " + x.hasAttributeNS(ns, "lang"); } ... The removeAttributeNS() method removes an attribute specified by namespace and name....