General

MSBuild XDT Transform

Transform a XML with the built-in XDT Transformation tool in MSBuild

  • #xml
  • #msbuild
  • #vs

XML can be transformed into a new version by going through the XDT transformation library built-in with Visual Studio.

Scenario

Imagine we have a XML configuration file that looks like this.

dev.config.xml
<website>
  <title>My Website</title>
  <environment>Development</environment>
  <url>http://localhost:8080</url>
</website>

The configuration are only for local/development environment. To cater for the production environment, we can just copy and paste the configuration and just change the relevant properties to the environment.

prod.config.xml
<website>
  <title>My Website</title>
  <environment>Production</environment>
  <url>https://www.mysite.com</url>
</website>

That is fine for minimal configurations. What if we have 1000 lines of configurations? The copy and paste approach becomes error-prone and difficult to maintain. It also creates redundancy as not all of the properties need to be changed as some are reused and shared across different environments.

Hence, what we can do is to extend the base XML file with XDT transform instead of copy pasta.

Syntax Introduction

This is how a XDT transformation looks like. It is still an XML file.

prod.config.xml
<?xml version="1.0" encoding="utf-8" ?>
<website xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <environment
    xdt:Locator="XPath(//website/environment)"
    xdt:Transform="Replace">Production</environment>
  <url
    xdt:Locator="XPath(//website/url)"
    xdt:Transform="Replace">https://www.mysite.com</url>
</website>

Here, we ignore the title because it is the same for all environment output and only transform the environment and url. The xdt:Locator indicates "Where is the original element" and xdt:Transform declares "How to manipulate it". These are the fundamental operators that the XDT transformation offers.

The idea is, this prod.config.xml will be processed by the XDT Transformation against the dev.config.xml and produce a fully structured counterpart just like a copy-paste would produce. The following step shows how to set up the transformation process.

Project Setup

First, create an empty Console project named MyXmlTransforms in Visual Studio. This is how the file tree should look like.

MyXmlTransforms/
โ”œโ”€โ”€ MyXmlTransforms.csproj
โ””โ”€โ”€ Program.cs

After that, remove the Program.cs file and create a folder called Base and put the dev.config.xml inside as well as a folder Prod and put prod.config.xml inside. After that update the MyXmlTransforms.csproj file to the following.

MyXmlTransforms.csproj
<Project Sdk="Microsoft.NET.Sdk" DefaultTargets="Transform">
    <PropertyGroup>
        <OutputType>Library</OutputType>
        <TargetFramework>net10.0</TargetFramework>
        <ImplicitUsings>enable</ImplicitUsings>
        <Nullable>enable</Nullable>
    </PropertyGroup>

    <PropertyGroup>
        <XdtDll>$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Web\Microsoft.Web.Publishing.Tasks.dll</XdtDll>
        <OutputDir>$(MSBuildThisFileDirectory)bin\Output\</OutputDir>
    </PropertyGroup>

    <UsingTask TaskName="TransformXml" AssemblyFile="$(XdtDll)" />

    <ItemGroup>
        <!-- Add more pairs here as needed -->
        <XmlTransform Include="Config">
            <Source>Base\dev.config.xml</Source>
            <Transform>Prod\prod.config.xml</Transform>
            <Destination>$(OutputDir)prod.config.xml</Destination>
        </XmlTransform>
    </ItemGroup>

    <Target Name="Transform" BeforeTargets="Build">
        <MakeDir Directories="$(OutputDir)" />
        <TransformXml Source="%(XmlTransform.Source)" Transform="%(XmlTransform.Transform)" Destination="%(XmlTransform.Destination)" StackTrace="true" />
        <Message Text="Transformed โ†’ %(XmlTransform.Destination)" Importance="high" />
    </Target>
</Project>

The %(...) batching syntax means MSBuild runs TransformXml once per item automatically โ€” no loops needed. StackTrace="true" on the task gives detailed error output if a transform fails โ€” useful while authoring.

Tldr,

  • XDT transform powered by the built-in Microsoft.Web.Publishing.Tasks.dll from Visual Studio
  • Declares a transformation pipeline that merges the dev and prod config file and outputs to the bin/Output directory
  • If you have more pairs of file to transform, duplicate the XmlTransform element and populate the properties with respect to the file

Then, execute the transformation by using the following commands.

msbuild WithXdt.csproj /t:Transform

Or simply

dotnet build

The file tree should now looks like this.

MyXmlTransforms/
โ”œโ”€โ”€ MyXmlTransforms.csproj
โ”œโ”€โ”€ Base/
โ”‚   โ””โ”€โ”€ dev.config.xml
โ”œโ”€โ”€ Prod/
โ”‚   โ””โ”€โ”€ prod.config.xml
โ””โ”€โ”€ bin/
    โ””โ”€โ”€ Output/              <-- created at build time

Common XDT Transform Attributes

Here are some of the common XDT operations.

Scenarioxdt:Transformxdt:Locator
Change an attributeSetAttributes(attrName)Match(keyAttr)
Replace entire elementReplaceMatch(...) or XPath(...)
Insert new elementInsert(none)
Remove an elementRemoveMatch(...) or XPath(...)
Remove an attributeRemoveAttributes(attrName)Match(...)

Summary

This guide covers the scenario of XDT transformation, simple syntax and project setup. Here is the similar project on GitHub for reference. For folder-based transformation, refer to this project.

References

Microsoft. Web.config Transformation Syntax for Web Project Deployment Using Visual Studio. Retrieved 2026, May 3 from https://sparkbyexamples.com/spark/apache-spark-installation-on-windows/
Web Config Transform.ย Logicmade Wiki. Retrieved 2026, May 3 from https://logicwiki.co.uk/Web_Config_Transform
Suwat, C. Xdt transform samples.https://github.com/projectkudu/kudu/wiki/Xdt-transform-samples
XPath Syntax. Retrieved 2026, May 3 from https://www.w3schools.com/xml/xpath_syntax.asp