views:

505

answers:

1

I'm using Nightly build 1.3.0.477 of MSBuild Community Tasks and I'm having problem with XmlMassUpdate.

Here's what I want to do:

for each project, if it does not reference CommonAssemblyInfo.cs file, add that reference.

I'm doing it like this:

<Message Text="Path is $(MSBuildCommunityTasksPath)" Importance="normal" />
<!---->
<XmlMassUpdate ContentFile="%(DotNetProjects.FullPath)"
      ContentRoot="msb:Project/msb:ItemGroup[2]/msb:Compile[1]"
      NamespaceDefinitions="msb=http://schemas.microsoft.com/developer/msbuild/2003"
      SubstitutionsFile="$(BuildFolder)CommonAssemblyInfo.substitution"
      SubstitutionsRoot="ItemGroup/Compile" />

my substitution file looks like this:

<ItemGroup>
    <Compile Include="..\..\CommonAssemblyInfo.cs" >
     <Link>Properties\CommonAssemblyInfo.cs</Link>
    </Compile>
</ItemGroup>

the issue is, when I run the target, it adds empty xmlns to the Link tag, which is illegal.

<ItemGroup>
<Compile Include="Class1.cs">
  <Link xmlns="">Properties\CommonAssemblyInfo.cs</Link>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>

How do I tell it not to do it?

+1  A: 

The short answer is you can't, the replace task always uses an empty namespace even if the substitution file's node has a namespace.

see: line 380 in XmlMassUpdate.cs destinationParentNode.AppendChild(mergedDocument.CreateNode(XmlNodeType.Element, nodeToModify.Name, String.Empty)

As an alternative you could use the XSLT task to transform the xml file.

I've included a basic example of how this might be done, but I'm not particularly proficient with XSLT so its a little hacked together.

<xsl:stylesheet
    version="1"
    xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
    xmlns:msb="http://schemas.microsoft.com/developer/msbuild/2003"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    >

    <xsl:output indent="yes"
            standalone="yes"
            method="xml"
            encoding="utf-8"
            />

    <xsl:template match="/msb:Project/msb:ItemGroup[1]">
        <ItemGroup>
            <Compile Include="..\..\CommonAssemblyInfo.cs">
                <Link>Properties\CommonAssemblyInfo.cs</Link>
            </Compile>
        </ItemGroup>
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

And in the build file.

<Xslt Inputs="input.xml"
      Output="output.xml"
      Xsl="transform.xslt"
      />
KeeperOfTheSoul
Thanks. I didn't want to go the XSLT path, because it felt too heavyweight, but I guess there's either this, or getting the XmlMassUpdate task... updated to ignore namespaces.
Krzysztof Koźmic
It would need to copy the namespace from the parent node its importing into.Though rather than ignore I'd probably have it copy the namespace from the original element, as you might want to merge a node under a different namespace, although this could be a breaking change for existing build files.Certainly worth filing a bug though.
KeeperOfTheSoul