C# XML Namespace “Fun”

I’ve been working with Visual Studio project files (csproj files) recently – they’re XML files. Now, if you open a csproj file in an editor, you’ll find items that look like this;

  <ItemGroup>
    <Compile Include="Behaviors\Behavior.cs" />
    <Compile Include="Behaviors\Rotator.cs" />
    <Compile Include="Behaviors\BodyRenderableBehavior.cs" />
    <Compile Include="Behaviors\ResistsCollission.cs" />
    <Compile Include="Goal.cs" />
    <Compile Include="GraphicsArgument.cs" />
    <Compile Include="Interfaces\ILevel.cs" />
    <Compile Include="Renderables\BodyHook.cs" />
    <Compile Include="Renderables\BodyHookOwners\BodyHookOwner.cs" />
.
.
.
  </ItemGroup>

These are the actual files that will get included compiled in the assembly. Now, using XElement and it’s descendants to locate these, you’d be forgiven for trying this out (but it won’t work);

        private static void Test(string projectFileName)
        {
            XElement root =
                XDocument.Load(projectFileName).Root;

            const string CompileTag = "Compile";

            List<XElement>
                compiles =
                    root
                        .Descendants(CompileTag)
                        .ToList();

            Console.WriteLine("Found these compiles:");
            compiles.ForEach(
                compile =>
                    Console.WriteLine(
                        "Compile: {0}",
                        compile.Attribute("Include").Value));
            Console.ReadKey();
        }

 

The printed list will be empty. The reason that it’s empty is that the <Compile /> nodes are located in a namespace, and the query above searches in the empty namespace.

You gotta prefix it with the namespace!

You’ll find the namespace in the xlmns attribute in the project root node header;

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="3.5" DefaultTargets="Build" 
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>

The namespace is this url;

http://schemas.microsoft.com/developer/msbuild/2003

So the simples way to change this code to work is to add this namespace to the search criteria. But how to format it? Debugging around a bit gave me the answer, place the namespace within curly-braces in the element name; “{namespace}TagName”. This code works;

        private static void Test(string projectFileName)
        {
            XElement root =
                XDocument.Load(projectFileName).Root;

            const string compileTag = "Compile";
            const string nameSpace = "{http://schemas.microsoft.com/developer/msbuild/2003}";

            List<XElement>
                compiles =
                    root
                        .Descendants(nameSpace + compileTag)
                        .ToList();

            Console.WriteLine("Found these compiles:");
            compiles.ForEach(
                compile =>
                    Console.WriteLine(
                        "Compile: {0}",
                        compile.Attribute("Include").Value));
            Console.ReadKey();
        }

 

You may wish to use the type-safe XNamespace and XName classes instead – note that if you use XNamespace, you can’t have the curly braces in the string;

        private static void Test(string projectFileName)
        {
            XElement root =
                XDocument.Load(projectFileName).Root;

            XNamespace nameSpace = "http://schemas.microsoft.com/developer/msbuild/2003";
            XName compileTag = nameSpace + "Compile";

            List<XElement>
                compiles =
                    root
                        .Descendants(compileTag)
                        .ToList();

            Console.WriteLine("Found these compiles:");
            compiles.ForEach(
                compile =>
                    Console.WriteLine(
                        "Compile: {0}",
                        compile.Attribute("Include").Value));
            Console.ReadKey();
        }

About mfagerlund
Writes code in my sleep - and sometimes it even compiles!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: