28

I have this code:

function setupProject($projectFile) {
  [xml]$root = Get-Content $projectFile;

  $project = $root.Project;

  $beforeBuild = $root.CreateElement("Target", "");
  $beforeBuild.SetAttribute("name", "BeforeBuild");
  $beforeBuild.RemoveAttribute("xmlns");
  $project.AppendChild($beforeBuild);

  $root.Save($projectFile);
}

It should add a new <Target name="BeforeBuild" /> to the XML document.

But it also adds an empty xmlns="" attribute which I don't want. (It's actually Visual Studio which doesn't like this attribute!)

<Target name="BeforeBuild" xmlns="" />

I've already tried this code:

$beforeBuild.RemoveAttribute("xmlns");
$project.AppendChild($beforeBuild);
$beforeBuild.RemoveAttribute("xmlns");
ComFreek
  • 29,044
  • 18
  • 104
  • 156

7 Answers7

34

The xmlns="" namespace (un)declaration has been added because your parent element is in a namespace and your child element is not.

If you don't want this namespace declaration added, the implication is that you want the child element to be in the same namespace as its parent, and the answer is to put it in this namespace at the time you create the element. That is, change the call CreateElement("Target", "") to specify the correct namespace.

mklement0
  • 382,024
  • 64
  • 607
  • 775
Michael Kay
  • 156,231
  • 11
  • 92
  • 164
  • 2
    But I don't have any namespace on the (direct) parent element. Only the root element `` has one: `xmlns="http://schemas.microsoft.com/developer/msbuild/2003"`. So should I pass this value to `CreateElement()`? – ComFreek Nov 05 '12 at 19:50
  • 1
    I can't see enough of your code to work out the detail (and I hate DOM programming anyway), but the fact that the serializer has added an xmlns="" declaration is pretty clear evidence that the parent is in a namespace (for whatever reason) and the child is not. – Michael Kay Nov 06 '12 at 18:14
  • 2
    Yes, you should give your new element the same namespace as the Project root element. Otherwise, it will add the xmlns attribute because the namespace is different from the parent. – Ash Jun 25 '13 at 21:20
  • 5
    Much better answer - solve the problem by specifying the correct namespace, then it will go away (because it's redundant information) – Simon Ejsing Sep 03 '13 at 09:20
  • 1
    solved my issue. i was fighting for last 4 hrs with this problem – Abhijeet Kamble Nov 16 '16 at 19:39
  • Thanks for the answer and comments the helped me solve the problem. In my case the root element of the XML has the attribute xmlns Using the namespace when creating a new xml element solved the issue with the unwanted attribute. ....CreateElement("EmbeddedResource", "http://schemas.microsoft.com/developer/msbuild/2003") – Kasper Jensen Dec 03 '20 at 18:38
20

As answered by Michael Kay, the best way to remove this unwanted namespace is creating the new child element in the same namespace as its parent:

function setupProject($projectFile) {
  [xml]$root = Get-Content $projectFile;

  $project = $root.Project;

  # UPDATE THIS LINE $beforeBuild = $root.CreateElement("Target", "");
  $beforeBuild = $root.CreateElement("Target", $project.NamespaceURI);
  $beforeBuild.SetAttribute("name", "BeforeBuild");
  $beforeBuild.RemoveAttribute("xmlns");
  $project.AppendChild($beforeBuild);

  $root.Save($projectFile);
}
mklement0
  • 382,024
  • 64
  • 607
  • 775
emekm
  • 742
  • 5
  • 9
14

Check these for possible solutions:

Powershell and csproj

Xml namespace and C# csproj

Here is a workaround from the second solution that worked for OP:

$content = [xml] $content.OuterXml.Replace(" xmlns=`"`"", "")
$content.Save($_.FullName);
Community
  • 1
  • 1
Victor Zakharov
  • 25,801
  • 18
  • 85
  • 151
  • 2
    Thanks for the links! The second solution worked for me. Could you please insert that code snippet into your answer? That'll be very helpful for other users. – ComFreek Nov 04 '12 at 15:54
  • 7
    Bad answer - it might work, but it suggests a fundamental misunderstanding about the cause of the problem. – Michael Kay Nov 05 '12 at 09:19
  • 3
    @MichaelKay: wrong attitude - an answer that works is a good answer. If you can suggest better, please go ahead (which you did already). – Victor Zakharov Nov 05 '12 at 12:15
1

Using Javascript

If you are using JS to create an XML doc and are getting blank xmlns attributes on child nodes after declaring xmlns="XXXX" on the parent node, use JS createElementNS(namespace, nodeName) instead of createElement(nodeName).

This is assuming you want your child nodes to share the same namespace as the parent. In the below case 'v1','v2', etc. will share the NS of 'data'

It would look something like this:

let data = someArray;
let nameSpace = 'XXX';
let doc = "<?xml version='1.0' encoding='utf-8' ?><data xmlns='XXXX'></data>";
let parser = new DOMParser();
let xml = parser.parseFromString(doc, "text/xml");

for (let i = 0; i < data.length; i++) {
    let node = xml.createElementNS(nameSpace , "v" + (i + 1));
    $(node).text(data[i]);
    let elements = xml.getElementsByTagName("data");
    elements[0].appendChild(node);
 }

CORRECT result would look like:

<?xml version='1.0' encoding='utf-8' ?>
<data xmlns='XXXX'>
    <v1></v1>
    <v2></v2>
</data>

Versus BAD result:

<?xml version='1.0' encoding='utf-8' ?>
<data xmlns='XXXX'>
    <v1 xmlns=""></v1>
    <v2 xmlns=""></v2>
</data>

With this solution, you could also declare separate Namespaces for your child nodes. Simply replace the nameSpace variable with a different namespace uri string or another set variable.

NSTuttle
  • 3,237
  • 2
  • 17
  • 26
1

The namespace is an inherent part of the name of each node.Removing namespace means need to recreate the node again. Here is the code, where you can create the child node without the Namespace property.

That means that if your main tag contains namespace attribute and your child doesn't have.Hence, the child node will inherit the defaulted namespace attribute from the parent. The best way to remove the namespace attribute is

[xml]$oXMLDocument = (Get-Content "D:\myXml.xml")
# Assuming Project is the parent node with a namespace
$project = $oXMLDocument.Project
$childNode = $oXMLDocument.CreateElement("test",$project.NamespaceURI)
# (Optional) Add any attributes to the element
$childNode.SetAttribute("name", "value")
$oXMLDocument.DocumentElement.AppendChild($childNode)
# Save the document
$oXMLDocument.Save("D:\myXml2.xml")

Basically, this will not remove the namespace attribute from the child note. And in fact you can't.This will hide the attribute as defaulted

If you need to create the subchild under your child node, then follow the same style.

Daniel Morritt
  • 1,787
  • 17
  • 25
zahid
  • 37
  • 6
  • The _code_ appears to be the virtually the same as in the [accepted answer](https://stackoverflow.com/a/35407581/45375), and your _explanation_ strikes me as inferior to the one in [this other answer](https://stackoverflow.com/a/13229110/45375) that the accepted one links to. What do you think your answer contributes? – mklement0 Oct 23 '20 at 22:45
1

I was having this problem building a web sitemap in VBA but @Neolisk got me on the right track. This solved my problem:

'replace the empty attribute with nothing and load it back into the XML source
myTree.LoadXML Replace(myTree.XML, " xmlns=""""", "")

'Write that XML to a file
myTree.Save xmlFileName

Thanks for the assist, @Neolisk!

0

The namespace is an inherent part of the name of each node.Removing namespace means need to recreate the node again. Here is the code, where you can create the child node without the Namespace property.

[xml]$oXmlDocume = [xml] (Get-Content  D:\myXml.xml)
// Assuming Project is the parent node
$project = $oXMLDocument.Project
$childNode = $oXMLDocument.CreateElement("Child",$project.NamespaceURI)
$0XMLDocument.AppendChild($ChildNode)

If you need to create the subchild under your child node, then follow the same style.

zahid
  • 37
  • 6
  • It looks like you later posted [another answer](https://stackoverflow.com/a/50161470/45375) that is simply an update of this one, so I suggest deleting this one. – mklement0 Oct 23 '20 at 22:35