Tools and library for applying XML Document Transformations to e.g. .NET configuration files, or any other XML-structured content.
.NET Core 2.1 introduces the concept of global tools,
meaning that you can install dotnet-xdt
using the .NET CLI and use it everywhere. One advantage of this approach
is that you can use the same command, for both installation and usage, across all platforms.
⚠️ To use global tools, .Net Core SDK 2.1.300 or later is required.
Install dotnet-xdt
as a global tool (only once):
dotnet tool install --global dotnet-xdt --version 2.2.1
And then you can apply XDT transforms, from the command-line, anywhere on your PC, e.g.:
dotnet xdt --source original.xml --transform delta.xml --output final.xml
Global tools are not ideal when an application needs to build completely self-contained, without relying on tools installed in the surrounding environment. They are also only available on the latest .NET Core.
Read on if this is a concern for your application.
.NET Core 2.0 and earlier do not support global tools.
The "classic" version of this tool, however, can be installed as a project-level tool on both the latest .NET Core, as well as on previous versions.
The tradeoff is that in this usage model, the tool can only be invoked
via dotnet transform-xdt
, and only from the folder of the project that references it.
See the project-level dotnet-transform-xdt
tool section
below for details. A separate repository provides a
few self-contained sample projects that use dotnet-transform-xdt
for Web.config transformations at publish time.
You can also download a standalone dotnet-xdt.exe
that runs on any Windows PC with .NET
Framework 4.6.1 installed. It has no external dependencies, nor does it require .NET Core.
It might run on Mono, but this scenario is not tested.
Download the latest build of dotnet-xdt.exe
from the releases page.
For complete flexibility, reference the cross-platform DotNet.Xdt
NuGet package in your application:
dotnet add package DotNet.Xdt --version 2.2.1
You can apply XDT transforms to any XML file, or other XML sources that can be read from
and written to a .NET Stream
.
Define a class MyXdtLogger
that implements IXmlTransformationLogger
.
Then, apply transformations using code similar to:
var document = new XmlTransformableDocument { PreserveWhitespace = true };
using (var sourceStream = File.OpenRead(sourceFilePath))
using (var transformStream = File.OpenRead(transformFilePath))
using (var transformation = new XmlTransformation(transformStream, new MyXdtLogger()))
{
document.Load(sourceStream);
transformation.Apply(document);
}
using (FileStream outputStream = File.Create(outputFilePath))
using (var outputWriter = XmlWriter.Create(outputStream, new XmlWriterSettings { Indent = true }))
{
document.WriteTo(outputWriter);
}
dotnet-xdt
is a global tool that can only be installed on .NET Core 2.1 or later.
dotnet-transform-xdt
is an alternative version that can be installed
as a project-level tool, on all .NET Core versions.
Note: if you are using project.json tooling (CLI 1.0.0 preview 2 or earlier, or Visual Studio 2015), please refer to the project.json section below.
Run dotnet --version
in a command prompt and make sure you're using version 2.0.0
or later.
Create a new folder (XdtSample
) and run dotnet new web
inside it. Verify that the files
XdtSample.csproj
and web.config
file are present. Create a new file named Web.Release.config
inside that folder and set its content to:
<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<system.webServer>
<aspNetCore>
<environmentVariables xdt:Transform="Insert">
<environmentVariable name="DOTNET_CLI_TELEMETRY_OPTOUT" value="1" />
</environmentVariables>
</aspNetCore>
</system.webServer>
</configuration>
We will use this sample XDT file to add an environment variable that disables dotnet CLI telemetry when
your project is published using the Release
configuration. See the MSDN XDT reference
for the complete transformation syntax.
Edit the XdtSample.csproj
file and inside an <ItemGroup>
element, add a reference to this XDT tool.
Note that you cannot use the NuGet Package Manager UI in Visual Studio 2017 to CLI tool references;
they must currently be added by editing the project file.
<ItemGroup>
<DotNetCliToolReference Include="Microsoft.DotNet.Xdt.Tools" Version="2.0.0" />
... other package references ...
</ItemGroup>
Run dotnet restore
and dotnet build
in the XdtSample
folder. If you now run dotnet transform-xdt
you will see the available options, similar to:
.NET Core XML Document Transformation
Usage: dotnet transform-xdt [options]
Options:
-?|-h|--help Show help information
--xml|-x The path to the XML file to transform
--transform|-t The path to the XDT transform file to apply
--output|-o The path where the output (transformed) file will be written
--verbose|-v Print verbose messages
So far we added the XDT tool to the project, and now we will invoke it when the project is being published.
We want to call it before the built-in publish target that makes sure that the Web.config
file has a reference
to the aspNetCore
handler, because that target always runs when publishing web projects, and it also formats
the config file to be nicely indented.
Edit the XdtSample.csproj
file and add this snippet at the end, right before the closing </Project>
tag:
<Project ToolsVersion="15.0" Sdk="Microsoft.NET.Sdk.Web">
... everything else ...
<Target Name="ApplyXdtConfigTransform" BeforeTargets="_TransformWebConfig">
<PropertyGroup>
<_SourceWebConfig>$(MSBuildThisFileDirectory)Web.config</_SourceWebConfig>
<_XdtTransform>$(MSBuildThisFileDirectory)Web.$(Configuration).config</_XdtTransform>
<_TargetWebConfig>$(PublishDir)Web.config</_TargetWebConfig>
</PropertyGroup>
<Exec
Command="dotnet transform-xdt --xml "$(_SourceWebConfig)" --transform "$(_XdtTransform)" --output "$(_TargetWebConfig)""
Condition="Exists('$(_XdtTransform)')" />
</Target>
</Project>
Here's a quick rundown of the values above:
BeforeTargets="_TransformWebConfig"
schedules this target to run before the build-in target that adds theaspNetCore
handler, as described earlier._SourceWebConfig
defines the full path to the Web.config file in your project folder. This will be used as the source (input) for the transformation._XdtTransform
defines the full path to the XDT transform file in your project folder to be applied. In this example, we useWeb.$(Configuration).config
, where $(Configuration) is a placeholder for the publish configuration, e.g.Debug
orRelease
._TargetWebConfig
defines the path where the transformedWeb.config
file will be written to, in the publish folder.Exec Command
invokes the XDT transform tool, passing the paths to the input file (Web.config
), transform file (e.g.Web.Release.config
) and target file (<publish-folder>\Web.config
).Exec Condition
prevents the XDT transform tool from running if a transform file for a particular publish configuration does not exist (e.g.Web.Debug.config
).
Now run dotnet publish
in the XdtSample
folder, and examine the Web.config
in the publish output folder
(bin\Debug\netcoreapp2.0\publish\Web.config
). It should look similar to this:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath="dotnet" arguments=".\XdtSample.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="false" />
</system.webServer>
</configuration>
Since we have not defined a Web.Debug.config
file, no transformation occured.
Now let's publish again, but this time using the Release
configuration. Run dotnet publish -c Release
in the XdtSample
folder, and examine the bin\Release\netcoreapp2.0\publish\Web.config
file.
It should look similar to this:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath="dotnet" arguments=".\XdtSample.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="false">
<environmentVariables>
<environmentVariable name="DOTNET_CLI_TELEMETRY_OPTOUT" value="1" />
</environmentVariables>
</aspNetCore>
</system.webServer>
</configuration>
Note that under <aspNetCore>
, the <environmentVariables>
section was inserted, as configured in the
Web.Release.config
file.
{
... other settings ...
"tools": {
"Microsoft.DotNet.Xdt.Tools": "1.0.0"
}
}
Using .NET Core 1.1 or ASP.NET Core 1.1?
In the sample above, replace 1.0.0
with 1.1.0
.
The typical use case is to transform Web.config
(or similar XML-based files) at publish time.
As an example, let's apply a transformation based on the publish configuration (i.e. Debug
vs.
Release
). Add a Web.Debug.config
file and a Web.Release.config
file to your project, in the
same folder as Web.config
file.
Call the tool from the scripts/postpublish
section of your project.json
to invoke it after publish:
{
"scripts": {
"postpublish": [
"dotnet transform-xdt --xml \"%publish:ProjectPath%\\Web.config\" --transform \"%publish:ProjectPath%\\Web.%publish:Configuration%.config\" --output \"%publish:OutputPath%\\Web.config\"",
"dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%"
]
}
}
The following options are passed to dotnet-transform-xdt
:
xml
: the input XML file to be transformed; in this example, theWeb.config
file in your project folder.transform
: the XDT file to be applied; in this example, theWeb.Debug.config
file in your project folder.output
: the XML file with the transformed output (input + XDT); in this example, theWeb.config
file in your publish folder (e.g.bin\Debug\win7-x64\publish
).
With the above setup, calling dotnet publish
from your project folder will apply the XDT transform
during the publishing process. The tool will print its output to the console, prefixed with
[XDT]
markers.
You can pass an explicit configuration (e.g. -c Debug
or -c Release
) to dotnet publish
to specify the configuration (and thus applicable XDT file) to publish. A similar option is available in the Visual
Studio publish dialog.
Please note that varying the applied transform by configuration as shown above is just an example. Any dotnet publish variable can be used to drive the transformation process.
To get a list of all available options, run dotnet transform-xdt
from the project folder:
.NET Core XML Document Transformation
Usage: dotnet transform-xdt [options]
Options:
-?|-h|--help Show help information
--xml|-x The path to the XML file to transform
--transform|-t The path to the XDT transform file to apply
--output|-o The path where the output (transformed) file will be written
--verbose|-v Print verbose messages