Search code examples
regexreplacemsbuildmsbuildextensionpack

How to Exclude Semicolons from MSBuild ExtensionPack.FileSystem.File Replacements


I'm using MSBuild extension pack to replace lines in .proj files. I'm replacing multiple lines with multiple lines. The lines it's outputting still have a semi colon at the end even when I do a transform.

<ItemGroup>
    <TestFile Include="regextest.xml" />
    <MyLines Include ="%3CItemGroup%3E%0A"/>
    <MyLines Include ="%09%3CReference Include=%22Stuff%22%3E%0A" />
    <MyLines Include ="%09%09%3CHintPath%3E..\..\packages\secret.dll%3C/HintPath%3E%0A" />
    <MyLines Include ="%09%09%3CPrivate%3ETrue%3C/Private%3E%0A" />
    <MyLines Include ="%09%3C/Reference%3E%0A" />
    <MyLines Include ="%3C/ItemGroup%3E%0A" />
</ItemGroup>


<Target Name="Default">
    <MSBuild.ExtensionPack.FileSystem.File TaskAction="Replace" 
      TextEncoding="ASCII" 
      RegexPattern="%3CProjectReference"
      RegexOptionList="IgnoreCase"
      Replacement="@(MyLines->'%(Identity)')"
      Files="@(TestFile)" />
</Target>

And this is the output:

<ItemGroup>
;   <Reference Include="Stuff">
;       <HintPath>..\..\packages\secret.dll</HintPath>
;       <Private>True</Private>
;   </Reference>
;</ItemGroup>

Doing it without the transform still has them there too.


Solution

  • One easy way to handle multi-line replacement strings is to form them in a CDATA block inside of a property instead of a collection of single-line items (this is where the semicolons come from). In this case, you could create the multi-line replacement string as a property and then assign its value to an item, then pass the item to the Replace task action:

    <PropertyGroup>
      <MyMultiLine>
      <![CDATA[
      %3CItemGroup%3E
        %3CReference Include="Stuff"%3E
          %3CHintPath%3E..\..\packages\secret.dll%3C/HintPath%3E
          %3CPrivate>True%3C/Private%3E
        %3C/Reference%3E
      %3C/ItemGroup%3E
      ]]>
      </MyMultiLine>
    </PropertyGroup>
    
    <ItemGroup>
      <TestFile Include="regextest.xml" />
      <MyMultiLineItem Include="$(MyMultiLine)" />
    </ItemGroup>
    
    <Target Name="Default">
        <MSBuild.ExtensionPack.FileSystem.File TaskAction="Replace" 
          TextEncoding="ASCII" 
          RegexPattern="%3CProjectReference"
          RegexOptionList="IgnoreCase"
          Replacement="@(MyMultiLineItem ->'%(Identity)')"
          Files="@(TestFile)" />
    </Target>