bigbearzhu
bigbearzhu

Reputation: 2451

How can I get rid of the namespace prefix from XElement like this (C#)?

I have got an xml string like this, and I am trying to deserialize it to an object with class Credentials. But the namespace prefix is stopping me.

The Credentials class itself doesn't have any XmlRoot attribute to set namespace. But some class which contains a Credentials property does. And the "ds" prefix below is from the container's serialized xml.

The container's xml is like this:

<ds:DataSource xmlns:ds="urn:My-Namespace">
    <ds:Credentials>
        <ds:UserName>foo</ds:UserName>
        <ds:Domain>bar</ds:Domain>
    </ds:Credentials>
</ds:DataSource>"

Then when I get the element "Credentials" from the containter element, it returns this:

<ds:Credentials xmlns:ds="urn:My-Namespace">
    <ds:UserName>foo</ds:UserName>
    <ds:Domain>bar</ds:Domain>
</ds:Credentials>

I can't deserialize this to a correct Credentials object because of the extra namespace. Is that possible to remove it? I have tried How to remove namespace prefix. (C#), the element still got a default namespace there.

<Credentials xmlns="urn:My-Namespace">
    <UserName>foo</UserName>
    <Domain>bar</Domain>
</Credentials>

Upvotes: 0

Views: 2076

Answers (2)

bigbearzhu
bigbearzhu

Reputation: 2451

Thanks for the inspiration of har07 and http://bohu7.wordpress.com/2008/12/11/removing-default-namespaces-from-an-xdocument/, I worked out the solution myself, it would keep normal attributes and remove other namespaces:

    public static void RemoveNamespace(this XElement element)
    {
        foreach (XElement e in element.DescendantsAndSelf())
        {
            if (e.Name.Namespace != XNamespace.None)
                e.Name = e.Name.LocalName;

            if (e.Attributes().Any(a => a.IsNamespaceDeclaration || a.Name.Namespace != XNamespace.None))
                e.ReplaceAttributes(e.Attributes().Select(NoNamespaceAttribute));
        }
    }

    private static XAttribute NoNamespaceAttribute(XAttribute attribute)
    {
        return attribute.IsNamespaceDeclaration
            ? null
            : attribute.Name.Namespace != XNamespace.None
                ? new XAttribute(attribute.Name.LocalName, attribute.Value)
                : attribute;
    }

Upvotes: 0

har07
har07

Reputation: 89295

There is an article in MSDN that can be adapted to do what you want : How to: Change the Namespace for an Entire XML Tree

Basically the article suggests to change Name of every XElement in the tree to a new Name (FYI, Name property contains information about the namespace and the local name). In this case, since we want to change each element to no namespace, you can change Name to the corresponding Name.LocalName :

var xml = @"<ds:DataSource xmlns:ds=""urn:My-Namespace"">
    <ds:Credentials>
        <ds:UserName>foo</ds:UserName>
        <ds:Domain>bar</ds:Domain>
    </ds:Credentials>
</ds:DataSource>";
var tree1 = XElement.Parse(xml);
foreach (XElement el in tree1.DescendantsAndSelf())
{
    el.Name = el.Name.LocalName;
    List<XAttribute> atList = el.Attributes().ToList();
    el.Attributes().Remove();
    foreach (XAttribute at in atList)
        el.Add(new XAttribute(at.Name.LocalName, at.Value));
}
//remove xmlns:ds="urn:My-Namespace"
tree1.RemoveAttributes();
//print result to console
Console.WriteLine(tree1.ToString());

Upvotes: 1

Related Questions