SlowCheetah - Web.config Transformation Syntax now generalized for any XML configuration file

http://www.hanselman.com/blog/SlowCheetahWebconfigTransformationSyntaxNowGeneralizedForAnyXMLConfigurationFile.aspx

I did a post last year called If You're Using XCopy, You're Doing It Wrong that also included a video of my talk at Mix10 where I show how to deploy website with Web Deploy. One of the cooler not-very-well-known features is called Web.config Transformation. Once folks see it, then immediately want a general solution.

First, from the previous post:

You can right-click on your web.config and click "Add Config Transforms." When you do this, you'll get a web.debug.config and a web.release.config. You can make a web.whatever.config if you like, as long as the name lines up with a configuration profile. These files are just the changes you want made, not a complete copy of your web.config.

You might think you'd want to use XSLT to transform a web.config, but while they feels intuitively right it's actually very verbose.

Here's two transforms, one using XSLT and the same one using the XML Document Transform syntax/namespace. As with all things there's multiple ways in XSLT to do this, but you get the general idea. XSLT is a generalized tree transformation language, while this deployment one is optimized for a specific subset of common scenarios. But, the cool part is that each XDT transform is a .NET plugin, so you can make your own.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="@*|node()">
  <xsl:copy>          
    <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
</xsl:template>
<xsl:template match="/configuration/appSettings">
  <xsl:copy>
    <xsl:apply-templates select="node()|@*"/>
    <xsl:element name="add">
      <xsl:attribute name="key">NewSetting</xsl:attribute>
      <xsl:attribute name="value">New Setting Value</xsl:attribute>
    </xsl:element>
  </xsl:copy>
</xsl:template>
</xsl:stylesheet>

Or the same thing via the deployment transform:

1
2
3
4
5
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
   <appSettings>
      <add name="NewSetting" value="New Setting Value" xdt:Transform="Insert"/>
   </appSettings>
</configuration>

This kind of config file transformation is so useful in fact, that it's one of the #1 feature requests...as a generalized solution. Folks want to transform their app.configs, or any XML file as part of their builds. Additionally, the current system only runs the transforms as a part of the publish process and folks would rather the transform happen "on F5" or on build. So, my team members Sayed Ibrahim Hashimi and Chuck England have done just that as a small VSiX called SlowCheetah XML Transforms.

In this screenshot I've created a simple Console Application, made a basic app.config, then right clicked and selected "Add Transform." This gives an app.debug.config and app.release.config. You could make and name these however you like, for example app.testing.config, etc.

An app.config file, the transform file, and the result in three panes

For example, here's a basic app.config for my Console app:

1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="utf-8" ?>
<configuration >
  <appSettings>
    <add key="appName" value="Something"/>
    <add key="url" value="http://hanselman.com/"/>
    <add key="email" value="awesome@hanselman.com" />
  </appSettings>
</configuration>

And here's the transform to change my one value in my development time config to a debug value (or test, staging, etc). You can do this for connectionStrings, app keys, compiler settings, anything in an XML or config file.

1
2
3
4
5
6
7
<?xml version="1.0" encoding="utf-8" ?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <appSettings>
    <add key="appName" value="Demo-debug" xdt:Transform="Replace" xdt:Locator="Match(key)"/>
    <add key="email" value="debug@contoso.com" xdt:Transform="Replace" xdt:Locator="Match(key)"/>
  </appSettings>
</configuration>

Note the Transform="Replace?" That can be replace, or insert, etc. Lots of choices. The ShowCheetah XML Transform Add-In also adds a "Preview Transform" right-click menu which makes writing these way easier.

The clever part is that there's no magic. All the functionality is installed to %LOCALAPPDATA%\Microsoft\MSBuild\SlowCheetah\v1\ and lives in a standard MSBuild .targets file. You don't even need the plugin if you are installing this on a build server, just copy the files or even check them in with your source and refer to them in your project or MSBuild files. It's added in your project file for you via the tooling like any custom targets:

1
<Import Project="$(LOCALAPPDATA)\Microsoft\MSBuild\SlowCheetah\v1\Microsoft.Transforms.targets" Condition="Exists('$(LOCALAPPDATA)\Microsoft\MSBuild\SlowCheetah\v1\Microsoft.Transforms.targets')" />

Between the build targets and the added menu items, you get:

  • Added tooling to desktop project to create XDT transforms
  • Ability to transform
    • app.config for desktop projects based on build configuration
    • any XML file to the output folder based on build configuration
  • Added tooling to enable previewing XDT transforms
  • For web projects you can easily transform other XML files during package/publish

Let Sayed and the team know what you think, if it's useful, and if you use it at Sayed's blog, or the SlowCheetah project site on the VS Gallery. Enjoy!

posted @ 2012-03-07 16:54  RobotTech  阅读(863)  评论(0编辑  收藏  举报