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?

Krzysztof Kozmic
  • 27,267
  • 12
  • 73
  • 115
  • Personally I'm not a fan of modifying the build files like this, I'd rather just have a check that each project contains this link and fails the build if it doesn't. – Chris Chilvers Aug 21 '09 at 09:51
  • I don't want to force onto developers things like this, that can be automated. I know it's usually a one-time operation, but anyway. – Krzysztof Kozmic Aug 21 '09 at 10:43

1 Answers1

2

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"
      />
Chris Chilvers
  • 6,429
  • 3
  • 32
  • 53
  • 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 Kozmic Aug 21 '09 at 10:41
  • 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. – Chris Chilvers Aug 21 '09 at 11:20