Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Modifying an XML via command line

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:

  1. An ad-hoc console application to patch the file with LINQ to XML - easiest
  2. Using XSLT - save a copy of the modified XML, later replacing the original (unless it's possible to transform the source XML in-place?)
  3. 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?"

like image 286
Igal Tabachnik Avatar asked Mar 09 '11 10:03

Igal Tabachnik


3 Answers

You may use the following XSLT command-line utilities for Microsoft XSLT processors:

  1. msxsl.exe (has been there for almost 10 years). Performs a transformation using MSXML (specifying different versions is possible).

  2. Oleg Tkachenko's nxslt.exe command line utility for XslCompiledTransform -- this is part of the Mvp.Xml project.

like image 192
Dimitre Novatchev Avatar answered Nov 03 '22 02:11

Dimitre Novatchev


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

like image 20
Filburt Avatar answered Nov 03 '22 04:11

Filburt


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.

like image 33
Dror Helper Avatar answered Nov 03 '22 04:11

Dror Helper