Partager via


Éléments MSBuild

Les éléments MSBuild sont des entrées dans le système de génération et représentent généralement des fichiers (les fichiers sont spécifiés dans l’attribut Include ). Les éléments sont regroupés en types d’éléments en fonction de leurs noms d’éléments. Les types d’éléments sont des listes nommées d’éléments qui peuvent être utilisés comme paramètres pour les tâches. Les tâches utilisent les valeurs d’élément pour effectuer les étapes du processus de génération.

Étant donné que les éléments sont nommés par le type d’élément auquel ils appartiennent, les termes « élément » et « valeur d’élément » peuvent être utilisés de façon interchangeable.

Créer des éléments dans un fichier projet

Vous déclarez des éléments dans le fichier projet en tant qu’éléments enfants d’un élément ItemGroup . Les noms d’éléments valides commencent par une lettre majuscule ou minuscule ou un trait de soulignement (_) ; les caractères suivants valides incluent des caractères alphanumériques (lettres ou chiffres), un trait de soulignement et un trait d’union (-). Le nom de l’élément enfant est le type de l’élément. L’attribut Include de l’élément spécifie les éléments (fichiers) à inclure dans ce type d’élément. Par exemple, le code XML suivant crée un type d’élément nommé Compile, qui inclut deux fichiers.

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

L’élément file2.cs ne remplace pas l’élément file1.cs ; Au lieu de cela, le nom de fichier est ajouté à la liste des valeurs pour le type d’élémentCompile.

Le code XML suivant crée le même type d’élément en déclarant les deux fichiers dans un Include attribut. Notez que les noms de fichiers sont séparés par un point-virgule.

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

L’attribut Include est un chemin d’accès interprété par rapport au dossier du fichier projet, $(MSBuildProjectPath)même si l’élément se trouve dans un fichier importé tel qu’un .targets fichier.

Créer des éléments pendant l’exécution

Les éléments qui se trouvent en dehors des éléments cibles sont attribués des valeurs pendant la phase d’évaluation d’une build. Pendant la phase d’exécution suivante, les éléments peuvent être créés ou modifiés de la manière suivante :

  • Toute tâche peut émettre un élément. Pour émettre un élément, l’élément Task doit avoir un élément Output enfant qui a un ItemName attribut.

  • La tâche CreateItem peut émettre un élément. Cette utilisation est déconseillée.

  • Target les éléments peuvent contenir des éléments ItemGroup qui peuvent contenir des éléments d’élément.

Éléments de référence dans un fichier projet

Pour référencer les types d’éléments dans le fichier projet, vous utilisez la syntaxe @(ItemType). Par exemple, vous référencez le type d’élément dans l’exemple précédent à l’aide @(Compile)de . À l’aide de cette syntaxe, vous pouvez transmettre des éléments à des tâches en spécifiant le type d’élément en tant que paramètre de cette tâche. Pour plus d’informations, consultez Guide pratique pour sélectionner les fichiers à générer.

Par défaut, les éléments d’un type d’élément sont séparés par des points-virgules (;) lorsqu’ils sont développés. Vous pouvez utiliser la syntaxe @(ItemType, 'separator') pour spécifier un séparateur autre que la valeur par défaut. Pour plus d’informations, consultez Guide pratique pour afficher une liste d’éléments séparée par des virgules.

Utiliser des caractères génériques pour spécifier des éléments

Vous pouvez utiliser les caractères génériques et ? les ***caractères génériques pour spécifier un groupe de fichiers en tant qu’entrées pour une build au lieu de répertorier chaque fichier séparément.

  • Le ? caractère générique correspond à un caractère unique.
  • Le * caractère générique correspond à zéro ou plusieurs caractères.
  • La ** séquence de caractères génériques correspond à un chemin d’accès partiel.

Par exemple, vous pouvez spécifier tous les .cs fichiers du répertoire qui contiennent le fichier projet à l’aide de l’élément suivant dans votre fichier projet.

<CSFile Include="*.cs"/>

L’élément suivant sélectionne tous les .vb fichiers sur le D: lecteur :

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

Si vous souhaitez inclure des littéraux * ou ? des caractères dans un élément sans extension générique, vous devez échapper aux caractères génériques.

Pour plus d’informations sur les caractères génériques, consultez Guide pratique pour sélectionner les fichiers à générer.

Utiliser l’attribut Exclude

Les éléments d’élément peuvent contenir l’attribut Exclude , qui exclut des éléments spécifiques (fichiers) du type d’élément. L’attribut Exclude est généralement utilisé avec des caractères génériques. Par exemple, le code XML suivant ajoute chaque fichier .cs dans le répertoire au CSFile type d’élément, à l’exception du fichier DoNotBuild.cs .

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

L’attribut Exclude affecte uniquement les éléments ajoutés par l’attribut dans l’élément Include d’élément qui les contient tous les deux. L’exemple suivant n’exclut pas le fichier Form1.cs, qui a été ajouté dans l’élément d’élément précédent.

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

Pour plus d’informations, consultez Guide pratique pour exclure les fichiers de la build.

Métadonnées de l’élément

Les éléments peuvent contenir des métadonnées en plus des informations contenues dans les attributs et Exclude les Include attributs. Ces métadonnées peuvent être utilisées par des tâches qui nécessitent plus d’informations sur les éléments ou pour traiter les tâches et les cibles par lots. Pour plus d’informations, consultez l’article Traitement par lot.

Les métadonnées sont une collection de paires clé-valeur déclarées dans le fichier projet en tant qu’éléments enfants d’un élément d’élément. Le nom de l’élément enfant est le nom des métadonnées, et la valeur de l’élément enfant est la valeur des métadonnées.

Les métadonnées sont associées à l’élément d’élément qui le contient. Par exemple, le code XML suivant ajoute Culture des métadonnées qui ont la valeur Fr à la fois au one.cs et aux éléments two.cs du CSFile type d’élément.

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

Un élément peut avoir zéro ou plusieurs valeurs de métadonnées. Vous pouvez modifier les valeurs de métadonnées à tout moment. Si vous définissez des métadonnées sur une valeur vide, vous la supprimez efficacement de la build.

Métadonnées d’élément de référence dans un fichier projet

Vous pouvez référencer les métadonnées d’élément tout au long du fichier projet à l’aide de la syntaxe %(ItemMetadataName). Si l’ambiguïté existe, vous pouvez qualifier une référence à l’aide du nom du type d’élément. Par exemple, vous pouvez spécifier %(ItemType.ItemMetaDataName). L’exemple suivant utilise les Display métadonnées pour traiter la Message tâche par lot. Pour plus d’informations sur l’utilisation des métadonnées d’élément pour le traitement par lots, consultez Métadonnées d’élément dans le traitement par lot des tâches.

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

Métadonnées d’élément connues

Lorsqu’un élément est ajouté à un type d’élément, cet élément est affecté à certaines métadonnées connues. Par exemple, tous les éléments ont les métadonnées %(Filename)connues, dont la valeur est le nom de fichier de l’élément (sans l’extension). Pour plus d’informations, consultez métadonnées d’élément connues.

Transformer des types d’éléments à l’aide de métadonnées

Vous pouvez transformer des listes d’éléments en nouvelles listes d’éléments à l’aide de métadonnées. Par exemple, vous pouvez transformer un type CppFiles d’élément qui contient des éléments qui représentent .cpp des fichiers en une liste correspondante de fichiers à l’aide de .obj l’expression @(CppFiles -> '%(Filename).obj').

Le code suivant crée un type d’élément CultureResource qui contient des copies de tous les EmbeddedResource éléments avec Culture des métadonnées. La Culture valeur des métadonnées devient la valeur des nouvelles métadonnées CultureResource.TargetDirectory.

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

Pour plus d’opérations sur les éléments, consultez les fonctions et transformations des éléments MSBuild.

Définitions d’éléments

Vous pouvez ajouter des métadonnées par défaut à n’importe quel type d’élément à l’aide de l’élément ItemDefinitionGroup. Comme les métadonnées connues, les métadonnées par défaut sont associées à tous les éléments du type d’élément que vous spécifiez. Vous pouvez remplacer explicitement les métadonnées par défaut dans une définition d’élément. Par exemple, le code XML suivant fournit les Compile éléments one.cs et three.cs les métadonnées BuildDay avec la valeur « Monday ». Le code donne à l’élément two.cs les métadonnées BuildDay avec la valeur « Tuesday ».

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

Pour plus d’informations, consultez définitions d’élément.

Attributs pour les éléments d’un ItemGroup d’une cible

Target les éléments peuvent contenir des éléments ItemGroup qui peuvent contenir des éléments d’élément. Les attributs de cette section sont valides lorsqu’ils sont spécifiés pour un élément d’un ItemGroup élément qui se trouve dans un Target.

Supprimer l’attribut

L’attribut Remove supprime des éléments spécifiques (fichiers) du type d’élément. Cet attribut a été introduit dans le .NET Framework 3.5 (à l’intérieur uniquement des cibles). Les cibles internes et externes sont prises en charge à partir de MSBuild 15.0.

L’exemple suivant supprime chaque .config fichier du type d’élément Compile .

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

Attribut MatchOnMetadata

L’attribut MatchOnMetadata s’applique uniquement aux Remove attributs qui référencent d’autres éléments (par exemple Remove="@(Compile);@(Content)") et indique à l’opération Remove de faire correspondre les éléments en fonction des valeurs des noms de métadonnées spécifiés, au lieu de correspondre en fonction des valeurs d’élément.

Règle de correspondance pour B Remove="@(A)" MatchOnMetadata="M": supprimez tous les éléments de B ces métadonnées M, dont la valeur V de métadonnées correspond M à n’importe quel élément à partir des A métadonnées M de valeur 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>

Dans l’exemple, les valeurs b2d’élément , c2et d2 sont supprimées de l’élément B , car :

  • b2 et c2 de B match contre b1 de A on M1=2 et M2=x
  • d2 des B correspondances par rapport c1 à partir d’on AM1=3 et M2=y

La Message tâche génère les résultats suivants :

  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'

Exemple d’utilisation de MatchOnMetadataMSBuild :

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

Cette ligne supprime les éléments dont les valeurs de _TransitiveItemsToCopyToOutputDirectory métadonnées sont identiques TargetPath dans _ThisProjectItemsToCopyToOutputDirectory

Attribut MatchOnMetadataOptions

Spécifie la stratégie de correspondance de chaîne utilisée pour MatchOnMetadata la correspondance des valeurs de métadonnées entre les éléments (les noms de métadonnées ne respectent toujours pas la casse). Les valeurs possibles sont CaseSensitive, CaseInsensitiveou PathLike. La valeur par défaut est CaseSensitive.

PathLike applique la normalisation prenant en charge les chemins aux valeurs telles que la normalisation des orientations de barre oblique, l’ignorance des barres obliques de fin, l’élimination . et ..la création de tous les chemins relatifs absolus par rapport au répertoire actif.

Attribut KeepMetadata

Si un élément est généré dans une cible, l’élément d’élément peut contenir l’attribut KeepMetadata . Si cet attribut est spécifié, seules les métadonnées spécifiées dans la liste délimitée par des points-virgules des noms seront transférées de l’élément source à l’élément cible. Une valeur vide pour cet attribut équivaut à ne pas la spécifier. L’attribut KeepMetadata a été introduit dans .NET Framework 4.5.

L’exemple suivant montre comment utiliser l’attribut 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:
-->

Attribut RemoveMetadata

Si un élément est généré dans une cible, l’élément d’élément peut contenir l’attribut RemoveMetadata . Si cet attribut est spécifié, toutes les métadonnées sont transférées de l’élément source à l’élément cible, à l’exception des métadonnées dont les noms sont contenus dans la liste délimitée par des points-virgules des noms. Une valeur vide pour cet attribut équivaut à ne pas la spécifier. L’attribut RemoveMetadata a été introduit dans .NET Framework 4.5.

L’exemple suivant montre comment utiliser l’attribut 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:
-->

Pour plus d’opérations sur les éléments, consultez les fonctions d’élément MSBuild.

Attribut KeepDuplicates

Si un élément est généré dans une cible, l’élément d’élément peut contenir l’attribut KeepDuplicates . KeepDuplicates est un Boolean attribut qui spécifie si un élément doit être ajouté au groupe cible si l’élément est un doublon exact d’un élément existant.

Si l’élément source et cible a la même Include valeur mais des métadonnées différentes, l’élément est ajouté même s’il KeepDuplicates est défini sur false. Une valeur vide pour cet attribut équivaut à ne pas la spécifier. L’attribut KeepDuplicates a été introduit dans .NET Framework 4.5.

L’exemple suivant montre comment utiliser l’attribut 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
-->

Étant donné que l’attribut KeepDuplicates considère les métadonnées des éléments en plus des valeurs d’élément, il est important de savoir ce qui se passe avec les métadonnées. Par exemple, consultez Détection des doublons lors de l’utilisation de la fonction d’élément de métadonnées.

Mise à jour des métadonnées sur les éléments d’un ItemGroup en dehors d’une cible

Les éléments en dehors des cibles peuvent avoir leurs métadonnées existantes mises à jour via l’attribut Update . Cet attribut n’est pas disponible pour les éléments sous cibles.

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

Dans MSBuild version 16.6 et ultérieure, l’attribut Update prend en charge les références de métadonnées qualifiées pour faciliter l’importation de métadonnées à partir de deux éléments ou plus.

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

Remarques:

  • Les métadonnées non qualifiées (%(MetadataName)) sont liées au type d’élément mis à jour (Item1 dans l’exemple ci-dessus). Les métadonnées qualifiées (%(Item2.Color)) sont liées à l’intérieur de l’ensemble de types d’éléments correspondants capturés à partir de l’expression Update.
  • Si un élément correspond plusieurs fois dans et entre plusieurs éléments référencés :
    • La dernière occurrence de chaque type d’élément référencé est capturée (par conséquent, un élément capturé par type d’élément).
    • Cela correspond au comportement du traitement par lots d’éléments de tâche sous les cibles.
  • Où l’on peut placer des références %() :
    • Métadonnées
    • Conditions de métadonnées
  • La correspondance des noms de métadonnées ne respecte pas la casse.

Mise à jour des métadonnées sur les éléments d’un ItemGroup d’une cible

Les métadonnées peuvent également être modifiées à l’intérieur des cibles, par une syntaxe moins expressive que 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:
-->