How to strip (or change) an XML namespace with XmlDocument

Part of the deployment scripts I'm working on must programmatically munge .NET config files. And I want to be able to use xpath expressions to index into them, but xpath is more painful (for what I'm doing at least) when namespaces are involved.

Sometimes config files look like this:

<configuration>...</configuration>

But they often also look like this:

<configuration xmlns='...'>...</configuration>

I needed a way to strip out the namespace before doing my queries. I found a solution and thought I'd share it here. XmlElement.SetAttribute can be used to change the namespace declaration (this is some special case code in the .NET DOM for this). But the change doesn't seem to take effect right away - I had to serialize the DOM tree and reload it, then things worked nicely. Here's a little function to do this:

XmlDocument stripDocumentNamespace(XmlDocument oldDom) {
    // some config files have a default namespace
    // we are going to get rid of that to simplify our xpath expressions
    if (oldDom.DocumentElement.NamespaceURI.Length > 0) {
        oldDom.DocumentElement.SetAttribute("xmlns", "");
        // must serialize and reload the DOM
        // before this will actually take effect
        XmlDocument newDom = new XmlDocument();
        newDom.LoadXml(oldDom.OuterXml);
        return newDom;
    }
    else return oldDom;
}

Posted Oct 19 2005, 05:00 PM by keith-brown
Filed under:

Comments

Keith Brown wrote re: How to strip (or change) an XML namespace with XmlDocument
on 10-20-2005 6:32 AM
Dan Sullivan (an authority on XML that I highly respect) points out that this is a very dangerous thing to do in the general case because it can lead to problems like duplicate names, etc.

I should probably have made it more clear that stripping namespaces is not to be taken lightly. I posted this to show not only how to strip namespaces, but how to *change* namespaces if necessary. Be careful that you know what you're doing if you strip. Here was my response to Dan:

This is a case where it's all the same namespace, which is why I pointed out that namespaces don't really matter in my case. I definitely thought about your concern, but from a purely practical perspective, the only reason the namespace is used in <configuration> is to get intellisense. So it seems pretty clear to me that stripping is very much appropriate in this case.

I'd never do this with a SOAP message, for example, where namespaces are used quite regularly, and are important for the meaning of the message.
Allan wrote re: How to strip (or change) an XML namespace with XmlDocument
on 10-20-2005 10:58 PM
Hi,
why not accept the namespaces :) and live with them....you should be able to query your config files by using the following code

XPathNavigator nav = xmlDoc.CreateNavigator();
XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable());
nsmgr.AddNamespace("xmlns","http://www.w3.org/2001/XMLSchema-instance");//or what ever that might be
XPathExpression expr = nav.Compile(xpathquery);
expr.SetContext(nsmgr);
XPathNodeIterator iter = nav.Select(expr);

cheers @llan
Keith Brown wrote re: How to strip (or change) an XML namespace with XmlDocument
on 10-21-2005 1:58 AM
Allan,

I actually went down that path first. But with xpath there is no way to define a default namespace for use inside expressions. So I'd have had to define a prefix for Microsoft's default config namespace, then used that in each location step of each xpath expression. Oh, and then I have to get everyone else I'm working with to agree on the namespace prefix we're all going to use in the xpath expressions. Ick!

Another option (Dan suggested this) would be to explicitly use local-name() in my xpath expressions. Both of these options clutter up the xpath expressions, which in this *particular* application would reduce the readability of what I'm doing enough that I figured it simply wasn't worth it.

Given MS's penchant for backwards compatibility, and given that it was only recently that we've seen namespaces in config files, I'm not worried that my code is going to break for the lifetime of this app.

It was a purely practical decision that really simplifies things. And it was soooo worth it in this case :-)
Christopher Steen wrote Link Listing - October 21, 2005
on 10-21-2005 6:32 AM
A Look at ASP.NET 2.0's Provider Model [Via: ]
ASP.NET Podcast #23 - Spang, Atlas and
life.... [Via:...
Robert Seso wrote re: How to strip (or change) an XML namespace with XmlDocument
on 10-26-2005 4:05 AM
It is also possible to strip all xmlns:* references from the XMLDocument using Regular Expressions:

XmlDocument stripDocumentNamespace(XmlDocument oldDom)
{
// Remove all xmlns:* instances from the passed XmlDocument
// to simplify our xpath expressions.
XmlDocument newDom = new XmlDocument();
newDom.LoadXml(System.Text.RegularExpressions.Regex.Replace(
oldDom.OuterXml, @"(xmlns:?[^=]*=[""][^""]*[""])", "",
System.Text.RegularExpressions.RegexOptions.IgnoreCase | System.Text.RegularExpressions.RegexOptions.Multiline)
);
return newDom;
}

This one gets rid of all "xmlns:{alias}" occurencies in the document, but you can limit it by making the Regex more restrictive if needed.

Regards, Robert
Ashwin wrote re: How to strip (or change) an XML namespace with XmlDocument
on 12-06-2006 4:40 AM
Mister Keith Brown,
Thank you very very much !!!!!!!!
rajesh wrote re: How to strip (or change) an XML namespace with XmlDocument
on 04-25-2007 11:42 AM
Thanks Keith. Your code snippet was helpful for my situation.
Ramir Borja wrote re: How to strip (or change) an XML namespace with XmlDocument
on 06-18-2007 7:13 PM
Keith and Robert, thanks for the code. Really simplifies things.
Fraser wrote re: How to strip (or change) an XML namespace with XmlDocument
on 09-21-2007 9:58 AM
This is exactly what I need but I'm not familiar enough with javascript to understand how to implement it. I am generating an xhtml document but I'm not able to set the proper namespace declaration in the generation process. The document ends up with:

xmlns:xf="http://www.example.org"

And to get the document to work properly i need to change the declaration to:

xmlns:xf="http://www.w3.org/2002/xforms"

Could I put your script in the head of the document to automatically change the namespace when the document loads?

Also, are old.Dom and new.Dom to be taken literally or should they be replaced by something?

Any tips would be greatly appreciated!!

Thanks,

Fraser
leoguy wrote re: How to strip (or change) an XML namespace with XmlDocument
on 09-24-2007 9:16 AM
Keith and Robert,
Thank you very much for your posts. Very nifty ideas. I ve been trying to do this for past 4 hours using SAX based processing but your ideas saved my day.

thanks again !
Matra wrote re: How to strip (or change) an XML namespace with XmlDocument
on 02-09-2008 11:37 PM
This can be very easily done with XSLT. Take a look at
http://www.xml.com/pub/a/2004/05/05/tr.html

Where you can find the following transformation:

<!-- Copy document, stripping namespaces, i.e. for elements

and attributes only copy the local part of their names. -->

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

<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:template match="processing-instruction()|comment()">

<xsl:copy>

<xsl:apply-templates select="node()"/>

</xsl:copy>

</xsl:template>

</xsl:stylesheet>


Matra
Siarhei Kuchuk wrote re: How to strip (or change) an XML namespace with XmlDocument
on 03-17-2008 10:17 PM
Thank you very much for your nice article and for marvellous regexp in comments of Robert Seso

You saved my time!


Thank's
Rans wrote re: How to strip (or change) an XML namespace with XmlDocument
on 03-24-2008 10:08 AM
Thanks guys..That was really helpful after an unproductive day of head breaking..

Add a Comment

(required)  
(optional)
(required)  
Remember Me?