Condividi tramite


Elementi di MSBuild

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

Poiché gli elementi sono denominati dal tipo di elemento a cui appartengono, i termini "item" e "item value" possono essere usati in modo intercambiabile.

Creare elementi in un file di progetto

Gli elementi nel file di progetto vengono dichiarati 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 (file) da includere in 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; Al contrario, il nome del file viene aggiunto all'elenco di valori per il Compile tipo di elemento.

Il codice XML seguente crea lo stesso tipo di elemento dichiarando entrambi i file in un Include attributo. Si noti che i nomi di file sono separati da un 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

Gli elementi esterni agli 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:

  • Qualsiasi attività può generare un elemento. Per generare un elemento, l'elemento Task deve avere un elemento Output figlio con un ItemName attributo .

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

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

Elementi di riferimento in un file di progetto

Per fare riferimento ai tipi di elemento nel file di progetto, usare la sintassi @(ItemType). Ad esempio, si fa riferimento al tipo di elemento nell'esempio precedente usando @(Compile). Usando questa sintassi, è possibile passare 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 sono separati da punti 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 .cs file 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 .vb file nell'unità D: :

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

Se si desidera includere caratteri letterali * o ? caratteri in un elemento senza espansione con caratteri jolly, è necessario eseguire l'escape dei caratteri jolly.

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

Usare l'attributo Exclude

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

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

L'attributo Exclude influisce solo sugli elementi aggiunti dall'attributo nell'elemento Include elemento che li contiene entrambi. L'esempio seguente non esclude il file Form1.cs, che è stato aggiunto nell'elemento dell'elemento precedente.

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

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

Metadati dell'elemento

Gli elementi possono contenere metadati oltre alle informazioni contenute negli Include attributi e Exclude . Questi metadati possono essere usati dalle attività che richiedono altre informazioni sugli elementi o per eseguire attività e destinazioni batch. Per ulteriori informazioni, vedere Raggruppamento.

I metadati sono una raccolta di coppie chiave-valore dichiarate nel file di progetto come elementi figlio di un elemento elemento. 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 che lo 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 metadati su un valore vuoto, è possibile rimuoverli 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). Se esistono 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 degli elementi per l'invio in batch, vedere Metadati degli elementi in batch delle attività.

<Project>
    <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 di elementi noti

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 degli elementi noti.

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 CultureResource tipo di elemento che contiene copie di tutti gli EmbeddedResource elementi con Culture metadati. Il Culture valore dei metadati 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 di elementi

È possibile aggiungere metadati predefiniti a qualsiasi tipo di elemento usando l'elemento ItemDefinitionGroup. Analogamente ai metadati noti, i metadati predefiniti sono associati a tutti gli elementi del tipo di elemento specificato. È possibile eseguire l'override esplicito dei metadati predefiniti in una definizione di elemento. Ad esempio, il codice XML seguente fornisce agli Compile elementi one.cs e three.cs i metadati BuildDay con il valore "Monday". Il codice fornisce 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 di 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.

Rimuovi attributo

L'attributo Remove rimuove elementi specifici (file) 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

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

Nell'esempio seguente viene illustrato come usare l'attributo KeepMetadata .

<Project>
    <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

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

Nell'esempio seguente viene illustrato come usare l'attributo RemoveMetadata .

<Project>

    <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

Se un elemento viene generato all'interno di una destinazione, l'elemento dell'elemento può contenere l'attributo KeepDuplicates . KeepDuplicates è un Boolean attributo 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 di destinazione ha lo stesso Include valore 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.

Nell'esempio seguente viene illustrato come usare l'attributo KeepDuplicates .

<Project>

    <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
    • 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:
-->