J'ai juste écrit un billet à ce sujet (http://sedodream.com/2011/12/29/UpdatingXMLFilesWithMSBuild.aspx), mais je vais coller l'info ici pour vous ainsi.
Aujourd'hui, j'ai juste vu une question postée sur StackOverflow demander comment mettre à jour un fichier XML à l'aide de MSBuild au cours de l'IC construire exécuté à partir de l'Équipe de la Ville.
Il n'est pas correct de réponse unique, il existe plusieurs façons différentes que vous pouvez mettre à jour un fichier XML lors d'une compilation. Plus particulièrement:
- Utilisation SlowCheetah de transformer les fichiers pour vous
- Utiliser le TransformXml tâche directement
- Utiliser le construit en (MSBuild 4.0) XmlPoke tâche
- L'utilisation d'un tiers de la tâche de la bibliothèque
1 Utilisez SlowCheetah de transformer les fichiers pour vous
Avant de démarrer la lecture trop loin dans ce post, laissez-moi aller sur l'option n ° 3 d'abord parce que je pense que c'est l'approche la plus simple et la plus facile à entretenir. Vous pouvez télécharger mon SlowCheetah XML Transforme Visual Studio s'ajouter. Une fois que vous faites cela, pour vos projets, vous verrez une nouvelle commande de menu pour transformer un fichier de construire (pour les projets web sur l'emballage/publier). Si vous souhaitez obtenir ce travail à partir d'un serveur CI, son assez facile de voir mon post à http://sedodream.com/2011/12/12/SlowCheetahXMLTransformsFromACIServer.aspx.
2 Utilisez les TransformXml tâche directement
Si vous voulez une technique où vous avez une "main" fichier XML et que vous voulez être en mesure de contenir les transformations de ce fichier à l'intérieur d'un fichier XML distinct, alors vous pouvez utiliser le TransformXml tâche directement. Pour plus d'infos, voir mon précédent billet de blog à http://sedodream.com/2010/11/18/XDTWebconfigTransformsInNonwebProjects.aspx
3 Utiliser le construit en XmlPoke tâche
Parfois, il n'est pas judicieux de créer un fichier XML avec des transformations pour chaque fichier XML. Par exemple, si vous avez un fichier XML et que vous souhaitez modifier une valeur unique, mais de créer des 10 différents fichiers XML approche de la transformation n'est pas à l'échelle. Dans ce cas, il pourrait être plus facile d'utiliser le XmlPoke tâche. Noter que cela ne nécessite MSBuild 4.0.
Ci-dessous le contenu de sample.xml (venu de la question).
<Provisioning.Lib.Processing.XmlConfig instancetype="XmlConfig, Processing, Version=1.0.0.0, Culture=neutral">
<item>
<key>IsTestEnvironment</key>
<value>True</value>
<encrypted>False</encrypted>
</item>
<item>
<key>HlrFtpPutDir</key>
<value>C:\DevPath1</value>
<encrypted>False</encrypted>
</item>
<item
<key>HlrFtpPutCopyDir</key>
<value>C:\DevPath2</value>
<encrypted>False</encrypted>
</item>
</Provisioning.Lib.Processing.XmlConfig>
Donc, dans ce cas, nous voulons mettre à jour les valeurs de l'élément de valeur. Donc, la première chose que nous devons faire est de venir avec le XPath correct de tous les éléments que nous voulons mettre à jour. Dans ce cas, on peut utiliser la suite des expressions XPath pour chaque élément de valeur.
- /Approvisionnement.Lib.La transformation.XmlConfig/item[key='HlrFtpPutDir']/valeur
- /Approvisionnement.Lib.La transformation.XmlConfig/item[key='HlrFtpPutCopyDir']/valeur
Je ne vais pas vous faire le point sur ce que vous devez faire pour trouver le bon XPath parce que ce n'est pas le but de ce post. Il y a un tas de XPath ressources connexes sur les interwebs. Dans la section ressources, j'ai lié à la mise en ligne XPath testeur que j'ai toujours utiliser.
Maintenant que nous avons obtenu le nécessaire expressions XPath nous avons besoin pour construire notre MSBuild des éléments afin d'obtenir tout mis à jour. Voici la technique de l'ensemble:
- Placez toutes les infos pour toutes les mises à jour XML dans un élément
- Utilisation XmlPoke avec MSBuild dosage à effectuer toutes les mises à jour
Pour le #2 si vous n'êtes pas familier avec MSBuild dosage, alors je vous recommande d'acheter mon livre ou, vous pouvez prendre un coup d'oeil sur les ressources que j'ai en ligne concernant le dosage (le lien est ci-dessous dans la section ressources). Vous trouverez ci-dessous un simple MSBuild fichier que j'ai créé, UpdateXm01.proj.
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="UpdateXml" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<SourceXmlFile>$(MSBuildProjectDirectory)\sample.xml</SourceXmlFile>
<DestXmlFiles>$(MSBuildProjectDirectory)\result.xml</DestXmlFiles>
</PropertyGroup>
<ItemGroup>
<!-- Create an item which we can use to bundle all the transformations which are needed -->
<XmlConfigUpdates Include="ConfigUpdates-SampleXml">
<XPath>/Provisioning.Lib.Processing.XmlConfig/item[key='HlrFtpPutDir']/value</XPath>
<NewValue>H:\ReleasePath1</NewValue>
</XmlConfigUpdates>
<XmlConfigUpdates Include="ConfigUpdates-SampleXml">
<XPath>/Provisioning.Lib.Processing.XmlConfig/item[key='HlrFtpPutCopyDir']/value</XPath>
<NewValue>H:\ReleasePath2</NewValue>
</XmlConfigUpdates>
</ItemGroup>
<Target Name="UpdateXml">
<Message Text="Updating XML file at $(DestXmlFiles)" />
<Copy SourceFiles="$(SourceXmlFile)"
DestinationFiles="$(DestXmlFiles)" />
<!-- Now let's execute all the XML transformations -->
<XmlPoke XmlInputPath="$(DestXmlFiles)"
Query="%(XmlConfigUpdates.XPath)"
Value="%(XmlConfigUpdates.NewValue)"/>
</Target>
</Project>
Les parties à accorder une attention particulière à est la XmlConfigUpdates article et le contenu de la UpdateXml tâche elle-même. Concernant la XmlConfigUpdates, ce nom est arbitraire, vous pouvez utiliser n'importe quel nom que vous voulez, vous pouvez voir que la valeur (qui sont généralement les points d'un fichier) est laissé à ConfigUpdates-SampleXml. La valeur de l'attribut include n'est pas utilisé ici. Je place en une valeur unique pour l'Inclure l'attribut pour chaque fichier de mise à jour. Cela fait juste plus facile pour les gens à comprendre ce que le groupe de valeurs est pour, et vous pouvez l'utiliser plus tard pour le lot de mises à jour. Le XmlConfigUpdates élément a ces deux valeurs de métadonnées:
- XPath
-- Il contient le XPath nécessaire pour sélectionner l'élément qui va être mis à jour
- NewValue
-- Il contient la nouvelle valeur de l'élément qui va être mis à jour
À l'intérieur de la UpdateXml cible, vous pouvez voir que nous sommes à l'aide de la XmlPoke tâche et en passant le XPath en %(XmlConfigUpdate.XPath) et la valeur en %(XmlConfigUpdates.NewValue). Puisque nous sommes à l'aide de l' %(...) de la syntaxe d'un élément de ce début de MSBuild traitement par lots. Le dosage est là plus qu'une opération est effectuée sur un "lot" de valeurs. Dans ce cas, il y a deux lots uniques (1 pour chaque valeur de XmlConfigUpdates) de sorte que le XmlPoke tâche sera invoqué à deux reprises. Le dosage peut être source de confusion, donc assurez-vous de lire si vous ne connaissez pas.
Maintenant, nous pouvons utiliser msbuild.exe pour démarrer le processus. Le fichier XML résultant est:
<Provisioning.Lib.Processing.XmlConfig instancetype="XmlConfig, Processing, Version=1.0.0.0, Culture=neutral">
<item>
<key>IsTestEnvironment</key>
<value>True</value>
<encrypted>False</encrypted>
</item>
<item>
<key>HlrFtpPutDir</key>
<value>H:\ReleasePath1</value>
<encrypted>False</encrypted>
</item>
<item>
<key>HlrFtpPutCopyDir</key>
<value>H:\ReleasePath2</value>
<encrypted>False</encrypted>
</item>
</Provisioning.Lib.Processing.XmlConfig>
Alors maintenant, nous pouvons voir combien il était facile d'utiliser le XmlPoke tâche. Nous allons maintenant jeter un oeil à la façon dont nous pouvons étendre cet exemple pour gérer les mises à jour pour le même fichier pour un environnement supplémentaire.
Comment gérer les mises à jour pour le même fichier pour plusieurs des résultats différents
Depuis, nous avons créé un élément qui va garder tout le nécessaire XPath ainsi que les nouvelles valeurs, nous avons un peu plus de souplesse dans la gestion de multiples environnements. Dans ce scénario, nous avons le même fichier que nous voulons écrire, mais nous avons besoin d'écrire des valeurs différentes en fonction de la cible de l'environnement. Cela est assez facile. Regardez le contenu de UpdateXml02.proj ci-dessous.
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="UpdateXml" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<SourceXmlFile>$(MSBuildProjectDirectory)\sample.xml</SourceXmlFile>
<DestXmlFiles>$(MSBuildProjectDirectory)\result.xml</DestXmlFiles>
</PropertyGroup>
<PropertyGroup>
<!-- We can set a default value for TargetEnvName -->
<TargetEnvName>Env01</TargetEnvName>
</PropertyGroup>
<ItemGroup Condition=" '$(TargetEnvName)' == 'Env01' ">
<!-- Create an item which we can use to bundle all the transformations which are needed -->
<XmlConfigUpdates Include="ConfigUpdates">
<XPath>/Provisioning.Lib.Processing.XmlConfig/item[key='HlrFtpPutDir']/value</XPath>
<NewValue>H:\ReleasePath1</NewValue>
</XmlConfigUpdates>
<XmlConfigUpdates Include="ConfigUpdates">
<XPath>/Provisioning.Lib.Processing.XmlConfig/item[key='HlrFtpPutCopyDir']/value</XPath>
<NewValue>H:\ReleasePath2</NewValue>
</XmlConfigUpdates>
</ItemGroup>
<ItemGroup Condition=" '$(TargetEnvName)' == 'Env02' ">
<!-- Create an item which we can use to bundle all the transformations which are needed -->
<XmlConfigUpdates Include="ConfigUpdates">
<XPath>/Provisioning.Lib.Processing.XmlConfig/item[key='HlrFtpPutDir']/value</XPath>
<NewValue>G:\SomeOtherPlace\ReleasePath1</NewValue>
</XmlConfigUpdates>
<XmlConfigUpdates Include="ConfigUpdates">
<XPath>/Provisioning.Lib.Processing.XmlConfig/item[key='HlrFtpPutCopyDir']/value</XPath>
<NewValue>G:\SomeOtherPlace\ReleasePath2</NewValue>
</XmlConfigUpdates>
</ItemGroup>
<Target Name="UpdateXml">
<Message Text="Updating XML file at $(DestXmlFiles)" />
<Copy SourceFiles="$(SourceXmlFile)"
DestinationFiles="$(DestXmlFiles)" />
<!-- Now let's execute all the XML transformations -->
<XmlPoke XmlInputPath="$(DestXmlFiles)"
Query="%(XmlConfigUpdates.XPath)"
Value="%(XmlConfigUpdates.NewValue)"/>
</Target>
</Project>
Les différences sont assez simples, j'ai introduit une nouvelle propriété, TargetEnvName qui nous permet de savoir quelle est la cible de l'environnement est. (remarque: je trouve simplement que le nom de la propriété, utiliser le nom que vous voulez). Aussi vous pouvez voir qu'il y a deux ItemGroup éléments contenant différents XmlConfigUpdate éléments. Chaque ItemGroup a une condition basée sur la valeur de TargetEnvName de sorte qu'une seule des deux ItemGroup valeurs seront utilisées. Maintenant, nous avons un seul fichier MSBuild qui a les valeurs pour les deux environnements. Lors de la construction de vient de passer dans la propriété TargetEnvName, par exemple msbuild .\UpdateXml02.proj /p:TargetEnvName=Env02. Quand j'ai exécuté ce le fichier qui en résulte contient:
<Provisioning.Lib.Processing.XmlConfig instancetype="XmlConfig, Processing, Version=1.0.0.0, Culture=neutral">
<item>
<key>IsTestEnvironment</key>
<value>True</value>
<encrypted>False</encrypted>
</item>
<item>
<key>HlrFtpPutDir</key>
<value>G:\SomeOtherPlace\ReleasePath1</value>
<encrypted>False</encrypted>
</item>
<item>
<key>HlrFtpPutCopyDir</key>
<value>G:\SomeOtherPlace\ReleasePath2</value>
<encrypted>False</encrypted>
</item>
</Provisioning.Lib.Processing.XmlConfig>
Vous pouvez voir que le fichier a été mis à jour avec des chemins différents dans la valeur de l'élément.
4 Utiliser un tiers de la tâche de la bibliothèque
Si vous n'êtes pas à l'aide de MSBuild 4, alors vous aurez besoin d'utiliser un tiers bibliothèque de tâches comme la MSBuild Pack d'Extension (lien dans les ressources).
Espérons que cela aide.
Ressources