Elementi MSBuild

Gli elementi MSBuild, forniti come input al sistema di compilazione, in genere rappresentano file. I file sono specificati nell'attributo Include. Gli elementi sono raggruppati in tipi di elemento in base ai nomi degli elementi. I tipi di elementi sono elenchi denominati di elementi che possono essere usati come parametri per le attività. Le attività usano i valori degli elementi per eseguire i passaggi del processo di compilazione.

Poiché gli elementi vengono denominati in base al tipo di elemento a cui appartengono, i termini "elemento" e "valore dell'elemento" sono interscambiabili.

Creare elementi in un file di progetto

Si dichiarano gli elementi nel file di progetto come elementi figlio di un elemento ItemGroup. I nomi degli elementi validi iniziano con una lettera maiuscola o minuscola o un carattere di sottolineatura (_); i caratteri successivi validi includono caratteri alfanumerici (lettere o cifre), carattere di sottolineatura e trattino (-). Il nome dell'elemento figlio è il tipo dell'elemento. L'attributo Include dell'elemento specifica gli elementi (i file) da includere con tale tipo di elemento. Ad esempio, il codice XML seguente crea un tipo di elemento denominato Compile che include due file.

<ItemGroup>
    <Compile Include = "file1.cs"/>
    <Compile Include = "file2.cs"/>
</ItemGroup>

L'elemento file2.cs non sostituisce l'elemento file1.cs. Il nome file viene invece aggiunto all'elenco di valori per il tipo di elemento Compile.

Il codice XML seguente crea lo stesso tipo di elemento dichiarando entrambi i file in un solo attributo Include. Si noti che i nomi file sono separati da punto e virgola.

<ItemGroup>
    <Compile Include = "file1.cs;file2.cs"/>
</ItemGroup>

L'attributo Include è un percorso interpretato rispetto alla cartella del file di progetto, $(MSBuildProjectPath), anche se l'elemento si trova in un file importato, ad esempio un .targets file.

Creare elementi durante l'esecuzione

Agli elementi non compresi in elementi Target vengono assegnati valori durante la fase di valutazione di una compilazione. Durante la fase di esecuzione successiva, gli elementi possono essere creati o modificati nei modi seguenti:

  • Le attività possono creare un elemento. Per creare un elemento, l'elemento Task deve avere un elemento Output figlio con un attributo ItemName.

  • L'attività CreateItem può creare un elemento. Questo utilizzo è deprecato.

  • Target gli elementi possono contenere elementi ItemGroup che possono contenere elementi dell'elemento.

Fare riferimento a elementi in un file di progetto

Per fare riferimento ai tipi di elemento nel file di progetto, usare la sintassi @(ItemType). Ad esempio, per fare riferimento al tipo di elemento nell'esempio precedente, si userà @(Compile). Usando questa sintassi, è possibile passare gli elementi alle attività specificando il tipo di elemento come parametro di tale attività. Per altre informazioni, vedere Procedura: Selezionare i file da compilare.

Per impostazione predefinita, gli elementi di un tipo di elemento vengono separati da punto e virgola (;) quando viene espanso. È possibile usare la sintassi @(ItemType, 'separator') per specificare un separatore diverso da quello predefinito. Per altre informazioni, vedere Procedura: Visualizzare un elenco di elementi separati da virgole.

Usare caratteri jolly per specificare gli elementi

È possibile usare i caratteri jolly **, * e ? per specificare un gruppo di file come input per una compilazione anziché elencare ogni file separatamente.

  • Il carattere jolly ? corrisponde a un singolo carattere.
  • Il carattere jolly * corrisponde a zero o più caratteri.
  • La sequenza di caratteri jolly ** corrisponde a un percorso parziale.

Ad esempio, è possibile specificare tutti i file .cs nella directory che contiene il file di progetto usando l'elemento seguente nel file di progetto.

<CSFile Include="*.cs"/>

L'elemento seguente seleziona tutti i file .vb nell'unità D::

<VBFile Include="D:/**/*.vb"/>

Se si desidera includere caratteri letterali * o ? in un elemento privo di espansione di caratteri jolly, è necessario aggiungere un carattere di escape ai caratteri jolly.

Per altre informazioni sui caratteri jolly, vedere Procedura: Selezionare i file da compilare.

Usare l'attributo Exclude

Gli elementi Item possono contenere l'attributo Exclude, che esclude elementi (file) specifici dal tipo di elemento. L'attributo Exclude viene in genere usato con i caratteri jolly. Ad esempio, il codice XML seguente aggiunge ogni file .cs nella directory al CSFile tipo di elemento, ad eccezione del file DoNotBuild.cs .

<ItemGroup>
    <CSFile  Include="*.cs"  Exclude="DoNotBuild.cs"/>
</ItemGroup>

L'attributo Exclude interessa solo gli elementi che vengono aggiunti dall'attributo Include nell'elemento item che li contiene entrambi. L'esempio seguente non escluderà il file Form1.cs, che è stato aggiunto nell'elemento item precedente.

<Compile Include="*.cs" />
<Compile Include="*.res" Exclude="Form1.cs">

Per altre informazioni, vedere Procedura: Escludere file dalla compilazione.

Metadati degli elementi

Gli elementi possono contenere metadati oltre alle informazioni negli attributi Include e Exclude. Questi metadati possono essere usati dalle attività che richiedono altre informazioni sugli elementi o per dividere in batch le attività e le destinazioni. Per altre informazioni, vedere Batch.

I metadati sono una raccolta di coppie chiave-valore che vengono dichiarate nel file di progetto come elementi figlio di un elemento item. Il nome dell'elemento figlio è il nome dei metadati e il valore dell'elemento figlio è il valore dei metadati.

I metadati sono associati all'elemento item che li contiene. Ad esempio, il codice XML seguente aggiunge Culture metadati con valore Fr sia al one.cs che agli elementi two.cs del CSFile tipo di elemento.

<ItemGroup>
    <CSFile Include="one.cs;two.cs">
        <Culture>Fr</Culture>
    </CSFile>
</ItemGroup>

Un elemento può avere zero o più valori di metadati. È possibile modificare i valori dei metadati in qualsiasi momento. Se si impostano i metadati su un valore vuoto, di fatto li si rimuove dalla compilazione.

Metadati degli elementi di riferimento in un file di progetto

È possibile fare riferimento ai metadati degli elementi nel file di progetto usando la sintassi %(ItemMetadataName). In caso di ambiguità, è possibile qualificare un riferimento usando il nome del tipo di elemento. Ad esempio, è possibile specificare %(ItemType.ItemMetaDataName). Nell'esempio seguente vengono usati i Display metadati per eseguire il batch dell'attività Message . Per altre informazioni su come usare i metadati di un elemento per la suddivisione in batch, vedere Metadati degli elementi nella suddivisione in batch delle attività.

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <ItemGroup>
        <Stuff Include="One.cs" >
            <Display>false</Display>
        </Stuff>
        <Stuff Include="Two.cs">
            <Display>true</Display>
        </Stuff>
    </ItemGroup>
    <Target Name="Batching">
        <Message Text="@(Stuff)" Condition=" '%(Display)' == 'true' "/>
    </Target>
</Project>

Metadati noti degli elementi

Quando un elemento viene aggiunto a un tipo di elemento, a tale elemento vengono assegnati alcuni metadati noti. Ad esempio, tutti gli elementi hanno i metadati %(Filename)noti , il cui valore è il nome file dell'elemento (senza l'estensione). Per altre informazioni, vedere Metadati noti degli elementi.

Trasformare i tipi di elemento usando i metadati

È possibile trasformare gli elenchi di elementi in nuovi elenchi di elementi usando i metadati. Ad esempio, è possibile trasformare un tipo di CppFiles elemento con elementi che rappresentano .cpp i file in un elenco corrispondente di .obj file usando l'espressione @(CppFiles -> '%(Filename).obj').

Il codice seguente crea un tipo di elemento CultureResource che contiene copie di tutti gli elementi EmbeddedResource con i metadati Culture. Il valore dei metadati Culture diventa il valore dei nuovi metadati CultureResource.TargetDirectory.

<Target Name="ProcessCultureResources">
    <ItemGroup>
        <CultureResource Include="@(EmbeddedResource)"
            Condition="'%(EmbeddedResource.Culture)' != ''">
            <TargetDirectory>%(EmbeddedResource.Culture) </TargetDirectory>
        </CultureResource>
    </ItemGroup>
</Target>

Per altre operazioni sugli elementi, vedere Funzioni degli elementi di MSBuild e Trasformazioni.

Definizioni degli elementi

È possibile aggiungere metadati predefiniti a qualsiasi tipo di elemento usando l'elemento ItemDefinitionGroup. Come i metadati noti, i metadati predefiniti sono associati a tutti gli elementi del tipo di elemento specificato. È possibile eseguire l'override esplicito dei metadati predefiniti nella definizione di un elemento. Il codice XML seguente, ad esempio, assegna agli elementi Compileone.cs e three.cs i metadati BuildDay con il valore "Monday". Il codice assegna all'elemento two.cs i metadati BuildDay con il valore "Tuesday".

<ItemDefinitionGroup>
    <Compile>
        <BuildDay>Monday</BuildDay>
    </Compile>
</ItemDefinitionGroup>
<ItemGroup>
    <Compile Include="one.cs;three.cs" />
    <Compile Include="two.cs">
        <BuildDay>Tuesday</BuildDay>
    </Compile>
</ItemGroup>

Per altre informazioni, vedere Definizioni degli elementi.

Attributi per gli elementi in un ItemGroup di una destinazione

Target gli elementi possono contenere elementi ItemGroup che possono contenere elementi dell'elemento. Gli attributi in questa sezione sono validi quando vengono specificati per un elemento in un ItemGroup oggetto che si trova in un oggetto Target.

Remove attribute

L'attributo Remove rimuove elementi (file) specifici dal tipo di elemento. Questo attributo è stato introdotto in .NET Framework 3.5 (solo all'interno di destinazioni). Le destinazioni interne e esterne sono supportate a partire da MSBuild 15.0.

Nell'esempio seguente viene rimosso ogni .config file dal Compile tipo di elemento.

<Target>
    <ItemGroup>
        <Compile Remove="*.config"/>
    </ItemGroup>
</Target>

Attributo MatchOnMetadata

L'attributo MatchOnMetadata è applicabile solo agli attributi che fanno riferimento ad Remove altri elementi (ad esempio, Remove="@(Compile);@(Content)") e indica all'operazione Remove di trovare le corrispondenze tra gli elementi in base ai valori dei nomi di metadati specificati, anziché la corrispondenza in base ai valori dell'elemento.

Regola di corrispondenza per B Remove="@(A)" MatchOnMetadata="M": rimuovere tutti gli elementi da B con metadati M, il cui valore V dei metadati per corrisponde a M qualsiasi elemento da A con i metadati M di valore V.

<Project>
  <ItemGroup>
    <A Include='a1' M1='1' M2='a' M3="e"/>
    <A Include='b1' M1='2' M2='x' M3="f"/>
    <A Include='c1' M1='3' M2='y' M3="g"/>
    <A Include='d1' M1='4' M2='b' M3="h"/>

    <B Include='a2' M1='x' m2='c' M3="m"/>
    <B Include='b2' M1='2' m2='x' M3="n"/>
    <B Include='c2' M1='2' m2='x' M3="o"/>
    <B Include='d2' M1='3' m2='y' M3="p"/>
    <B Include='e2' M1='3' m2='Y' M3="p"/>
    <B Include='f2' M1='4'        M3="r"/>
    <B Include='g2'               M3="s"/>

    <B Remove='@(A)' MatchOnMetadata='M1;M2'/>
  </ItemGroup>

  <Target Name="PrintEvaluation">
    <Message Text="%(B.Identity) M1='%(B.M1)' M2='%(B.M2)' M3='%(B.M3)'" />
  </Target>
</Project>

Nell'esempio i valori b2dell'elemento , c2e d2 vengono rimossi dall'elemento B perché:

  • b2 e c2 dalla B partita contro b1 da A on M1=2 e M2=x
  • d2 dalle B corrispondenze contro c1 da on AM1=3 e M2=y

L'attività Message restituisce quanto segue:

  a2 M1='x' M2='c' M3='m'
  e2 M1='3' M2='Y' M3='p'
  f2 M1='4' M2='' M3='r'
  g2 M1='' M2='' M3='s'

Esempio di utilizzo di MatchOnMetadata da MSBuild:

      <_TransitiveItemsToCopyToOutputDirectory Remove="@(_ThisProjectItemsToCopyToOutputDirectory)" MatchOnMetadata="TargetPath" MatchOnMetadataOptions="PathLike" />

Questa riga rimuove gli elementi da _TransitiveItemsToCopyToOutputDirectory con gli stessi TargetPath valori di metadati dagli elementi in _ThisProjectItemsToCopyToOutputDirectory

Attributo MatchOnMetadataOptions

Specifica la strategia di corrispondenza delle stringhe usata da MatchOnMetadata per trovare la corrispondenza dei valori dei metadati tra gli elementi (i nomi dei metadati sono sempre senza distinzione tra maiuscole e minuscole). I valori possibili sono CaseSensitive, CaseInsensitiveo PathLike. Il valore predefinito è CaseSensitive.

PathLike applica la normalizzazione compatibile con il percorso ai valori come la normalizzazione degli orientamenti delle barre, ignorando le barre finali, eliminando . e ..e rendendo assoluti tutti i percorsi relativi rispetto alla directory corrente.

Attributo KeepMetadata

Un elemento item, se viene generato in una destinazione, può contenere l'attributo KeepMetadata. Se questo attributo è specificato, solo i metadati specificati nell'elenco di nomi delimitati da punto e virgola verranno trasferiti dall'elemento di origine a quello di destinazione. Un valore vuoto per questo attributo equivale a non specificarlo. L'attributo KeepMetadata è stato introdotto in .NET Framework 4.5.

L'esempio seguente mostra come usare l'attributo KeepMetadata.

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
ToolsVersion="4.0">

    <ItemGroup>
        <FirstItem Include="rhinoceros">
            <Class>mammal</Class>
            <Size>large</Size>
        </FirstItem>

    </ItemGroup>
    <Target Name="MyTarget">
        <ItemGroup>
            <SecondItem Include="@(FirstItem)" KeepMetadata="Class" />
        </ItemGroup>

        <Message Text="FirstItem: %(FirstItem.Identity)" />
        <Message Text="  Class: %(FirstItem.Class)" />
        <Message Text="  Size:  %(FirstItem.Size)"  />

        <Message Text="SecondItem: %(SecondItem.Identity)" />
        <Message Text="  Class: %(SecondItem.Class)" />
        <Message Text="  Size:  %(SecondItem.Size)"  />
    </Target>
</Project>

<!--
Output:
  FirstItem: rhinoceros
    Class: mammal
    Size:  large
  SecondItem: rhinoceros
    Class: mammal
    Size:
-->

Attributo RemoveMetadata

Un elemento item, se viene generato in una destinazione, può contenere l'attributo RemoveMetadata. Se questo attributo è specificato, tutti i metadati vengono trasferiti dall'elemento di origine all'elemento di destinazione, a eccezione dei metadati i cui nomi sono contenuti nell'elenco di nomi separati da punto e virgola. Un valore vuoto per questo attributo equivale a non specificarlo. L'attributo RemoveMetadata è stato introdotto in .NET Framework 4.5.

L'esempio seguente mostra come usare l'attributo RemoveMetadata.

<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

    <PropertyGroup>
        <MetadataToRemove>Size;Material</MetadataToRemove>
    </PropertyGroup>

    <ItemGroup>
        <Item1 Include="stapler">
            <Size>medium</Size>
            <Color>black</Color>
            <Material>plastic</Material>
        </Item1>
    </ItemGroup>

    <Target Name="MyTarget">
        <ItemGroup>
            <Item2 Include="@(Item1)" RemoveMetadata="$(MetadataToRemove)" />
        </ItemGroup>

        <Message Text="Item1: %(Item1.Identity)" />
        <Message Text="  Size:     %(Item1.Size)" />
        <Message Text="  Color:    %(Item1.Color)" />
        <Message Text="  Material: %(Item1.Material)" />
        <Message Text="Item2: %(Item2.Identity)" />
        <Message Text="  Size:     %(Item2.Size)" />
        <Message Text="  Color:    %(Item2.Color)" />
        <Message Text="  Material: %(Item2.Material)" />
    </Target>
</Project>

<!--
Output:
  Item1: stapler
    Size:     medium
    Color:    black
    Material: plastic
  Item2: stapler
    Size:
    Color:    black
    Material:
-->

Per altre operazioni sugli elementi, vedere Funzioni dell'elemento MSBuild.

Attributo KeepDuplicates

Un elemento item, se viene generato in una destinazione, può contenere l'attributo KeepDuplicates. KeepDuplicates è un attributo Boolean che specifica se un elemento deve essere aggiunto al gruppo di destinazione se l'elemento è un duplicato esatto di un elemento esistente.

Se l'elemento di origine e destinazione hanno lo stesso valore Include, ma metadati diversi, l'elemento viene aggiunto anche se KeepDuplicates è impostato su false. Un valore vuoto per questo attributo equivale a non specificarlo. L'attributo KeepDuplicates è stato introdotto in .NET Framework 4.5.

L'esempio seguente mostra come usare l'attributo KeepDuplicates.

<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

    <ItemGroup>
        <Item1 Include="hourglass;boomerang" />
        <Item2 Include="hourglass;boomerang" />
    </ItemGroup>

    <Target Name="MyTarget">
        <ItemGroup>
            <Item1 Include="hourglass" KeepDuplicates="false" />
            <Item2 Include="hourglass" />
        </ItemGroup>

        <Message Text="Item1: @(Item1)" />
        <Message Text="  %(Item1.Identity)  Count: @(Item1->Count())" />
        <Message Text="Item2: @(Item2)" />
        <Message Text="  %(Item2.Identity)  Count: @(Item2->Count())" />
    </Target>
</Project>

<!--
Output:
  Item1: hourglass;boomerang
    hourglass  Count: 1
    boomerang  Count: 1
  Item2: hourglass;boomerang;hourglass
    hourglass  Count: 2
    boomerang  Count: 1
-->

Poiché l'attributo KeepDuplicates considera i metadati degli elementi oltre ai valori dell'elemento, è importante sapere cosa accade con i metadati. Ad esempio, vedere Rilevamento di duplicati quando si usa la funzione Elemento metadati.

Aggiornamento dei metadati per gli elementi in un ItemGroup all'esterno di una destinazione

Gli elementi esterni alle destinazioni possono avere i metadati esistenti aggiornati tramite l'attributo Update . Questo attributo non è disponibile per gli elementi nelle destinazioni.

<Project>
    <PropertyGroup>
        <MetadataToUpdate>pencil</MetadataToUpdate>
    </PropertyGroup>

    <ItemGroup>
        <Item1 Include="stapler">
            <Size>medium</Size>
            <Color>black</Color>
            <Material>plastic</Material>
        </Item1>
        <Item1 Include="pencil">
            <Size>small</Size>
            <Color>yellow</Color>
            <Material>wood</Material>
        </Item1>
        <Item1 Include="eraser">
            <Color>red</Color>
        </Item1>
        <Item1 Include="notebook">
            <Size>large</Size>
            <Color>white</Color>
            <Material>paper</Material>
        </Item1>

        <Item2 Include="notebook">
            <Size>SMALL</Size>
            <Color>YELLOW</Color>
        </Item2>

        <!-- Metadata can be expressed either as attributes or as elements -->
        <Item1 Update="$(MetadataToUpdate);stapler;er*r;@(Item2)" Price="10" Material="">
            <Color>RED</Color>
        </Item1>
    </ItemGroup>

    <Target Name="MyTarget">
        <Message Text="Item1: %(Item1.Identity)
    Size: %(Item1.Size)
    Color: %(Item1.Color)
    Material: %(Item1.Material)
    Price: %(Item1.Price)" />
    </Target>
</Project>

<!--  
Item1: stapler
    Size: medium
    Color: RED
    Material:
    Price: 10
Item1: pencil
    Size: small
    Color: RED
    Material:
    Price: 10
Item1: eraser
    Size:
    Color: RED
    Material:
    Price: 10
Item1: notebook
    Size: large
    Color: RED
    Material:
    Price: 10
-->

In MSBuild versione 16.6 e successive, l'attributo Update supporta riferimenti ai metadati qualificati per facilitare l'importazione di metadati da due o più elementi.

<Project>
    <ItemGroup>
        <Item1 Include="stapler">
            <Size>medium</Size>
            <Color>black</Color>
            <Material>plastic</Material>
        </Item1>
        <Item1 Include="pencil">
            <Size>small</Size>
            <Color>yellow</Color>
            <Material>wood</Material>
        </Item1>
        <Item1 Include="eraser">
            <Size>small</Size>
            <Color>red</Color>
            <Material>gum</Material>
        </Item1>
        <Item1 Include="notebook">
            <Size>large</Size>
            <Color>white</Color>
            <Material>paper</Material>
        </Item1>

        <Item2 Include="pencil">
            <Size>MEDIUM</Size>
            <Color>RED</Color>
            <Material>PLASTIC</Material>
            <Price>10</Price>
        </Item2>

        <Item3 Include="notebook">
            <Size>SMALL</Size>
            <Color>BLUE</Color>
            <Price>20</Price>
        </Item3>

        <!-- Metadata can be expressed either as attributes or as elements -->
        <Item1 Update="@(Item2);er*r;@(Item3)" Size="%(Size)" Color="%(Item2.Color)" Price="%(Item3.Price)" Model="2020">
            <Material Condition="'%(Item2.Material)' != ''">Premium %(Item2.Material)</Material>
        </Item1>
    </ItemGroup>

    <Target Name="MyTarget">
        <Message Text="Item1: %(Item1.Identity)
    Size: %(Item1.Size)
    Color: %(Item1.Color)
    Material: %(Item1.Material)
    Price: %(Item1.Price)
    Model: %(Item1.Model)" />
    </Target>
</Project>

<!--  
Item1: stapler
    Size: medium
    Color: black
    Material: plastic
    Price:
    Model:
Item1: pencil
    Size: small
    Color: RED
    Material: Premium PLASTIC
    Price:
    Model: 2020
Item1: eraser
    Size: small
    Color:
    Material: gum
    Price:
    Model: 2020
Item1: notebook
    Size: large
    Color:
    Material: paper
    Price: 20
    Model: 2020
-->

Note:

  • I metadati non qualificati (%(MetadataName)) vengono associati al tipo di elemento da aggiornare (Item1 nell'esempio precedente). I metadati qualificati (%(Item2.Color)) vengono associati all'interno del set di tipi di elementi corrispondenti acquisiti dall'espressione Update.
  • Se un elemento corrisponde più volte all'interno e tra più elementi a cui si fa riferimento:
    • L'ultima occorrenza di ogni tipo di elemento a cui viene fatto riferimento viene acquisita (quindi un elemento acquisito per ogni tipo di elemento).
    • Questo corrisponde al comportamento dell'invio in batch degli elementi dell'attività nelle destinazioni.
  • Dove è possibile inserire %() riferimenti:
    • Metadati UFX
    • Condizioni dei metadati
  • La corrispondenza dei nomi dei metadati non fa distinzione tra maiuscole e minuscole.

Aggiornamento dei metadati per gli elementi in un ItemGroup di una destinazione

I metadati possono essere modificati anche all'interno delle destinazioni, con una sintassi meno espressiva di Update:

<Project>
    <ItemGroup>
        <Item1 Include="stapler">
            <Size>medium</Size>
            <Color>black</Color>
            <Material>plastic</Material>
        </Item1>
        <Item1 Include="pencil">
            <Size>small</Size>
            <Color>yellow</Color>
            <Material>wood</Material>
        </Item1>
        <Item1 Include="eraser">
            <Size>small</Size>
            <Color>red</Color>
            <Material>gum</Material>
        </Item1>
        <Item1 Include="notebook">
            <Size>large</Size>
            <Color>white</Color>
            <Material>paper</Material>
        </Item1>

        <Item2 Include="pencil">
            <Size>MEDIUM</Size>
            <Color>RED</Color>
            <Material>PLASTIC</Material>
            <Price>10</Price>
        </Item2>

        <Item2 Include="ruler">
            <Color>GREEN</Color>
        </Item2>

    </ItemGroup>

    <Target Name="MyTarget">
        <ItemGroup>
            <!-- Metadata can be expressed either as attributes or as elements -->
            <Item1 Size="GIGANTIC" Color="%(Item2.Color)">
                <Material Condition="'%(Item2.Material)' != ''">Premium %(Item2.Material)</Material>
            </Item1>
        </ItemGroup>

        <Message Text="Item1: %(Item1.Identity)
    Size: %(Item1.Size)
    Color: %(Item1.Color)
    Material: %(Item1.Material)
    Price: %(Item1.Price)
    Model: %(Item1.Model)" />
    </Target>
</Project>

<!--  
Item1: stapler
    Size: GIGANTIC
    Color: GREEN
    Material: Premium PLASTIC
    Price:
    Model:
Item1: pencil
    Size: GIGANTIC
    Color: GREEN
    Material: Premium PLASTIC
    Price:
    Model:
Item1: eraser
    Size: GIGANTIC
    Color: GREEN
    Material: Premium PLASTIC
    Price:
    Model:
Item1: notebook
    Size: GIGANTIC
    Color: GREEN
    Material: Premium PLASTIC
    Price:
    Model:
-->