Search code examples
msbuildsandcastle

How to convert ItemGroup into Propertygroup in MSBUILD


I found a similar question like this here.

But this doesn't solve my problem. I have a ItemGroup like this

<ItemGroup>
    <DocumentationSource Include="TestLibrary\TestLibrary.csproj;TestLibrary2\TestLibrary2.csproj;TestLibrary2\TestLibrary3.csproj" />
</ItemGroup>

I need to change this into propertygroup in this format

<PropertyGroup>
    <DocumentationSources>
      <DocumentationSource sourceFile="TestLibrary\TestLibrary.csproj" />
      <DocumentationSource sourceFile="TestLibrary2\TestLibrary2.csproj" />
      <DocumentationSource sourceFile="TestLibrary2\TestLibrary3.csproj" />
    </DocumentationSources>
</PropertyGroup>

I am using sandcastle document builder for generating documents. That needs the document source as I shown in the format of PropertyGroup. But in my build script already I have a ItemGroup which has all the project as mentioned in the above format.

How to use that ItemGroup here as document source of SandCastle or how to convert the ItemGroup to PropertyGroup in the above format?

Actually I can change the ItemGroup to the PropertyGroup format but that has been formed dynamically with some logic like this

 <_ProjectFilesPlatform Include="%(ProjectDefinitionsPlatform.Identity)">
        <_ProjectPath>$([System.String]::Copy(%(ProjectDefinitionsPlatform.Identity)).Replace(".","\"))</_ProjectPath>
      </_ProjectFilesPlatform>

[This is a rough outline I gave here. This manipulation is not the actual one used]

I am new to this MSBUILD scripts. Can anyone throw some light on this ?

Thanks.


Solution

  • You can use the @() syntax to transform the items to a string, separated by newlines. Here is an example project file (tested with MSBuild 15 on .net core):

    <Project>
      <ItemGroup>
        <DocumentationSource Include="TestLibrary\TestLibrary.csproj;TestLibrary2\TestLibrary2.csproj;TestLibrary2\TestLibrary3.csproj" />
      </ItemGroup>
    
      <PropertyGroup>
        <DocumentationSources>
          @(DocumentationSource->'&lt;DocumentationSource sourceFile="%(Identity)" /&gt;', '
          ')
        </DocumentationSources>
      </PropertyGroup>
    
      <Target Name="Build">
        <Message Importance="high" Text="Value of DocumentationSources: $(DocumentationSources)" />
      </Target>
    </Project>
    

    Which produces the following output:

    $ dotnet msbuild
    Microsoft (R) Build Engine version 15.3.378.6360 for .NET Core
    Copyright (C) Microsoft Corporation. All rights reserved.
    
      Value of DocumentationSources: 
            <DocumentationSource sourceFile="TestLibrary/TestLibrary.csproj" />
            <DocumentationSource sourceFile="TestLibrary2/TestLibrary2.csproj" />
            <DocumentationSource sourceFile="TestLibrary2/TestLibrary3.csproj" />
    

    This even allows you to use a wildcard for your item element:

    <DocumentationSource Include="**\*.csproj" />