And over the XML we go…

Feeling like Homer Simpson…

Sorry for being out of touch for so long.  We had to get ready for beta in a foreign country and we’re rocking and rolling toward full production.  (I now have less hair!)  It’s all fun, but I had an issue that came up and the MSDN forums indicated it could be a duplicate Project GUID.   Since we create our own project files (we have special needs J), I thought that was very possible.  So in 15 minutes, I threw together a utility that would walk every directory and read every project file and look for duplicates.  Seemed simple enough, however, my

DocumentElement.SelectSingleNode("//Project/PropertyGroup/ProjectGuid")

was always returning null!

 

The project file was simple enough:

<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003&quot; ToolsVersion="2.0">

  <PropertyGroup>

    <BinplaceToBinariesFolder>true</BinplaceToBinariesFolder>

    <BinplaceToSymbolsFolder>true</BinplaceToSymbolsFolder>

  </PropertyGroup>

  <Import Project="$(NTMAKEENV)My.Build.settings" />

  <PropertyGroup>

    <ProjectGuid>{71440C14-ED89-4FF0-B1EF-3A217CC6887D}</ProjectGuid>

    <OutputType>library</OutputType>

    <RootNamespace>My.Namespace.MyAssembly</RootNamespace>

    <AssemblyName>MyAssembly</AssemblyName>

    <SignAssembly>true</SignAssembly>

    <AssemblyOriginatorKeyFile>….My.snk</AssemblyOriginatorKeyFile>

    <StyleCopEnabled>true</StyleCopEnabled>

    <DocumentationFile>$(IntermediateOutputPath)$(AssemblyName).xml</DocumentationFile>

  </PropertyGroup>

                        … rest goes here …

</Project>

 

And the code to retrieve the ProjectGuid was simple enough as well:

// Load the project file

                        XmlDocument doc = new XmlDocument();

                        doc.Load(fileName);

                        // retrieve the Project Guid

                        XmlNode node = doc.DocumentElement.SelectSingleNode("//Project/PropertyGroup/ProjectGuid");

                        // do something here . . .

 

OK, I thought, I’m a smart guy, I know it’s a namespace problem.  I can see in the project that there is a default namespace and according to the MSDN documentation for XmlNamespaceManager, to make a default namespace you use:

String.Empty

The empty namespace. This value can be assigned to a prefix. For example, xmlns="" defines the default namespace to be the empty namespace.

 

So I updated the code as follows:

// Load the project file

                        XmlDocument doc = new XmlDocument();

                        doc.Load(fileName);

                        // create a default namespace

                        XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);

                        nsmgr.AddNamespace("", "http://schemas.microsoft.com/developer/msbuild/2003&quot;);

                        // get the Project Guid

                        XmlNode node = doc.DocumentElement.SelectSingleNode("//Project/PropertyGroup/ProjectGuid", nsmgr);

                        // do something here . . .

 

But still nothing!  Thanks to a co-worker who whacked me in the back of the head saying “We dealt with this before” (to be honest, he had forgotten at first too!).   The docs are incorrect when using a default namespace.  You do have to give it a prefix.  So the correct code was:

                        // Load the project file

                        XmlDocument doc = new XmlDocument();

                        doc.Load(fileName);

                        // create a default namespace

                        XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);

                        nsmgr.AddNamespace("a", "http://schemas.microsoft.com/developer/msbuild/2003&quot;);

                        // get the Project Guid

                        XmlNode node = doc.DocumentElement.SelectSingleNode("//a:Project/a:PropertyGroup/a:ProjectGuid", nsmgr);

 

Now this is all fine and dandy and I’m glad I had it re-implanted into my brain cells.  However, it’s not all that performant.  Now, for what I was doing (building a utility), it didn’t matter as much, but for production quality code, performance does matter.  One of the reasons it’s not too speedy is that it loads the XML into the DOM.  To use an XmlReader, we could use the code below:

 

                        // create a reader

                        XmlTextReader xmlReader = new XmlTextReader(fileName);

                        // read until…

                        while (xmlReader.Read())

                        {

                                                switch (xmlReader.NodeType)

                                                {

                                                                        // use the NodeType to look for an element

                                                                        case XmlNodeType.Element:

                                                                                                // we find an element named "ProjectGuid"

                                                                                                if (xmlReader.Name == "ProjectGuid")

                                                                                                {

                                                                                                                        // use xmlReader.ReadString() to get the value of the element

                                                                                               

                                                                                                                        // do something here

                                                                                                }

                                                                                                break;

                                                                        }

                                                }

                        }

 

 

Pretty simple stuff, but yet can trip you up and make you waste time (which none of us have enough of!).

 

Hope that helps and happy coding!

 

 

Advertisements

About JohnMarkHowell

I am a professional software developer with over 20 years of experience. I currently specialize in Microsoft technologies such as VS, TFS, C#, VB.Net, WCF, WPF, WW, etc.
This entry was posted in Uncategorized. Bookmark the permalink.

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