Wednesday 20 August 2008

XML Namespaces and LINQ to XML

Recently I've been writing a program to automatically generate an MSBuild file containing all of our projects. This is then used by CruiseControl.NET to continuously build and test our source code.

I decided to use the new LINQ to XML to write the MSBuild file, but came across a problem when I ran the resulting file through MSBuild. The error message I received was:
The element beneath element may not have a custom XML namespace.

Investigation revealed that the root node of the MSBuild XML has a XML namespace (xmlns="http://schemas.microsoft.com/developer/msbuild/2003") and when I added a new XElement to the root element it automatically added a blank namespace attribute to the XElement(xmlns=""). Thus causing the error message.

The solution is to always add a XNamespace object of the SAME address to the XElement you are adding (see below).
XNamespace _xlmns = "http://schemas.microsoft.com/developer/msbuild/2003";

XElement root = new XElement(_xlmns + "Project",
new XAttribute("DefaultTargets", "Build");

XElement newBuildTarget = new XElement(_xlmns + "MSBuild",
new XAttribute("Projects", notShownSolutionPath),
new XAttribute("Targets", notShownTargets));
root.Add(XElement);

Bizarrely enough this will actually then remove the xmlns attribute from the added element. But thankfully it solves the problem.

No comments: