Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to remove xmlns attribute of a node other than root in an XDocument?

Situation

I'm using XDocument to try and remove an xmlns="" attribute on the first inner node:

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

So what I want as a result is:

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

Code

doc = XDocument.Load(XmlReader.Create(inStream));

XElement inner = doc.XPathSelectElement("/*/*[1]");
if (inner != null)
{
    inner.Attribute("xmlns").Remove();
}

MemoryStream outStream = new MemoryStream();
XmlWriter writer = XmlWriter.Create(outStream);
doc.Save(writer); // <--- Exception occurs here

Problem

Upon trying to save the document, I get the following exception:

The prefix '' cannot be redefined from '' to 'http://my.namespace' within the same start element tag.

What does this even mean and what can I do to remove that pesky xmlns=""?

Notes

  • I do want to keep the root node's namespace
  • I only want that specific xmlns removed, there will be no other xmlns attributes in the document.

Update

I've tried using code inspired from answers on this question:

inner = new XElement(inner.Name.LocalName, inner.Elements());

When debugging, the xmlns attribute is gone from it but I get the same exception.

like image 956
MarioDS Avatar asked Jun 19 '14 11:06

MarioDS


People also ask

How do I get rid of xmlns?

Open the map in the Design Studio. Edit the output card in question (in this case output card 1 of the validationMap map) and expand it so you can right click on Property > Schema > Type > Metadata > Name Spaces > http://www.example.com/IPO. After right clicking on http://www.example.com/IPO, left click on Delete.

Where can you define the xmlns attribute?

XML Namespaces - The xmlns Attribute The namespace can be defined by an xmlns attribute in the start tag of an element. The namespace declaration has the following syntax. xmlns:prefix="URI".

Why do we use Xmlns in XML?

One of the primary motivations for defining an XML namespace is to avoid naming conflicts when using and re-using multiple vocabularies. XML Schema is used to create a vocabulary for an XML instance, and uses namespaces heavily.


2 Answers

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");
        // All elements with an empty namespace...
        foreach (var node in doc.Root.Descendants()
                                .Where(n => n.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(...)
    }
}
like image 169
Jon Skeet Avatar answered Oct 17 '22 15:10

Jon Skeet


There is no need to 'remove' the empty xmlns attribute. The whole reason that the empty xmlns attrib is added is because the namespace of your childnodes is empty (= '') and therefore differ from your root node. Adding the same namespace to your childs as well will solve this 'side-effect'.

XNamespace xmlns = XNamespace.Get("http://my.namespace");

// wrong
var doc = new XElement(xmlns + "Root", new XElement("Firstelement"));

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

// right
var doc = new XElement(xmlns + "Root", new XElement(xmlns + "Firstelement"));

// gives:
<Root xmlns="http://my.namespace">
    <Firstelement />
</Root>
like image 23
Andries Avatar answered Oct 17 '22 13:10

Andries