I'm looking for a better way to patch an XML (actually, app.config
file). More specifically, I need to add something to the <appConfig>
section (which might not exist), as well as several <bindingRedirect>
elements to matching entries.
I also need this as a开发者_开发百科 command-line tool, for easier deployment.
I thought about solving this in several ways:
- An ad-hoc console application to patch the file with LINQ to XML - easiest
- Using XSLT - save a copy of the modified XML, later replacing the original (unless it's possible to transform the source XML in-place?)
- Using XML Diff and Patch, however it seems that the diffgram produced refers to exact node locations, such as
<xd:node match="1">
, etc.
The ad-hoc solution is the easiest, but I feel it's a bit cheating. I don't know XSLT very well, but it sounds like the best solution...
What, in your opinion, is the "best tool for the job?"
You may use the following XSLT command-line utilities for Microsoft XSLT processors:
msxsl.exe (has been there for almost 10 years). Performs a transformation using MSXML (specifying different versions is possible).
Oleg Tkachenko's nxslt.exe command line utility for XslCompiledTransform -- this is part of the Mvp.Xml project.
If using Xslt would be an option you could use MSBuild to drive the transformation on the command line.
Configuration file app.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="myAssembly" publicKeyToken="32ab4ba45e0a69a1" culture="neutral" />
<bindingRedirect oldVersion="1.0.0.0" newVersion="2.0.0.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
Xslt appconfig.xslt
This sample xslt would copy everything from your source app.config and add a <appSetting />
node if it doesn't exist:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<xsl:apply-templates />
</xsl:template>
<xsl:template match="configuration">
<xsl:element name="configuration">
<xsl:if test="self::node()[not(appSettings)]">
<xsl:element name="appSettings" />
</xsl:if>
<xsl:apply-templates />
</xsl:element>
</xsl:template>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
MSBuild script appconfig.proj
This sample MSBuild project script will copy/backup your source app.config and transform it with the given xslt stylesheet.
<Project ToolsVersion="4.0" DefaultTargets="Transform" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<AppConfigFile Include="app.config" />
</ItemGroup>
<Target Name="Clone">
<Copy SourceFiles="@(AppConfigFile)" DestinationFiles="clone.config">
<Output TaskParameter="CopiedFiles" ItemName="ClonedConfig" />
</Copy>
</Target>
<Target Name="Transform" DependsOnTargets="Clone">
<XslTransformation XslInputPath="appconfig.xslt" XmlInputPaths="@(ClonedConfig)" OutputPaths="app.config" />
</Target>
</Project>
Running it from the command line
<path to .NET framework 4>\MSBuild.exe appconfig.proj
In my experience using XSLT might work but keep in mind you would like to maintain it as well. There's a good tool for constructing xslt visual called MapForce I've used in the past that might help.
Recently at work I needed to do a similar task - convert XML file from format A to format B - using Linq was the quickest and easiest why and currently also easy to maintain.
So my suggestion is do the simlest thing that work and go for quick solution unless you have clear benefits from using XSLT instead.
精彩评论