Giter Site home page Giter Site logo

cameronwills / fatantelope Goto Github PK

View Code? Open in Web Editor NEW
84.0 11.0 20.0 190 KB

A tool for comparing .NET .config files and generating a config transform (Microsoft Xml Document Transform).

License: Other

C# 100.00%
xml comparison xdiff comparison-algorithm xdt configs

fatantelope's Introduction

FatAntelope

A tool for comparing two .config files and generating an XDT transform (Microsoft XML Document Transform). Useful for creating config transforms for existing production web.config or app.config files.

Build status Release NuGet Stars

How it works

FatAntelope parses the two config (xml) files into two trees and performs an unordered diff / comparison to identify nodes that have been updated, inserted or deleted, and then generates a XDT transform from these differences.

The XML diff / comparison algorithm is a C# port of the 'XDiff' algorithm described here: http://pages.cs.wisc.edu/~yuanwang/xdiff.html

Try It

A demonstration is setup here: fatantelopetester-app.azurewebsites.net

Download

Download the command-line tool in releases

Usage

Following build, you can use reference the FatAntelope.Core library directly or otherwise run the command-line tool

Command Line Syntax

FatAntelope source-file target-file output-file [transformed-file]

   source-file : (input) original config file path.  E.g. the development web.config

   target-file : (input) final config file path.  E.g. the production web.config

   output-file : (output) file path to save the generated patch.  E.g. web.release.config

   transformed-file : (output, optional) file path to save the result from applying the output-file to the source-file.

Example

FatAntelope app.config prod_app.config app.release.config

Source File (app.config):

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
  </startup>
  <connectionStrings>
    <add name="Users" connectionString="Data Source=127.0.0.1;initial catalog=UserDB;user id=myUser;password=myPassword" providerName="System.Data.EntityClient" />
    <add name="Posts" connectionString="Data Source=127.0.0.1;initial catalog=PostDB;user id=myUser;password=myPassword" providerName="System.Data.EntityClient" />
  </connectionStrings>
  <appSettings>
    <add key="MyUrl" value="http://localhost:50634" />
    <add key="MyService.Api" value="http://localhost:10424" />
  </appSettings>
</configuration>

Target File (prod_app.config) :

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
  </startup>
  <connectionStrings>
    <add name="Users" connectionString="Data Source=203.1.1.1;initial catalog=UserDB;user id=myUser;password=myPassword" providerName="System.Data.EntityClient" />
    <add name="Posts" connectionString="Data Source=203.1.1.1;initial catalog=PostDB;user id=myUser;password=myPassword" providerName="System.Data.EntityClient" />
  </connectionStrings>
  <appSettings>
    <add key="MyUrl" value="http://MyAmazingWebsite.com" />
    <add key="MyService.Api" value="http://MyAmazingWebsite.com/Api" />
  </appSettings>
</configuration>

Patch File (app.release.config) :

<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <connectionStrings>
    <add name="Users" xdt:Locator="Match(name)" connectionString="Data Source=203.1.1.1;initial catalog=UserDB;user id=myUser;password=myPassword" xdt:Transform="SetAttributes(connectionString)" />
    <add name="Posts" xdt:Locator="Match(name)" connectionString="Data Source=203.1.1.1;initial catalog=PostDB;user id=myUser;password=myPassword" xdt:Transform="SetAttributes(connectionString)" />
  </connectionStrings>
  <appSettings>
    <add key="MyUrl" xdt:Locator="Match(key)" value="http://MyAmazingWebsite.com" xdt:Transform="SetAttributes(value)" />
    <add key="MyService.Api" xdt:Locator="Match(key)" value="http://MyAmazingWebsite.com/Api" xdt:Transform="SetAttributes(value)" />
  </appSettings>
</configuration>

Caveats

  • The generated XDT transform may not have the most optimal values for the xdt:Locator and xdt:Transform attributes. I recommend only using this output as a starting-point for your transforms.

  • The XML comparison algorithm used (XDiff) does an unordered comparison of XML nodes, so changes to child elements' position within the same parent will be ignored.

Why 'FatAntelope'

A fat antelope for a slow cheetah

FatAntelope

fatantelope's People

Contributors

cameronwills avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fatantelope's Issues

Incorrect condition?

Hi there

Check it out
Source web.config

<configuration>  
  <appSettings>
    <add key="MyService.Api" value="0" />
  </appSettings>  
</configuration>

Target web.config

<configuration>  
  <appSettings>
    <add key="MyService.Api" value="1" />
    <add key="MyService.Api" value="2" />    
  </appSettings>  
</configuration>

Transformation

<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <appSettings>
    <add xdt:Locator="Condition([(@value='1')])" value="1" xdt:Transform="SetAttributes(value)" />
    <add key="MyService.Api" value="2" xdt:Transform="Insert" />
  </appSettings>
</configuration>

What gives us the next result

<configuration>  
  <appSettings>
    <add key="MyService.Api" value="0" />
  <add key="MyService.Api" value="2" /></appSettings>  
</configuration>

Should not the condition to be xdt:Locator="Condition([(@value='0')])"?

remove namespace xdt did not work

I have base.xml and target.xml, and I want to apply the target to base.
1.base.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
  <appSettings>
    <add key="test20180523" value="1" />
  </appSettings>
</configuration>

2.target.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <appSettings>
    <add key="test20180523" value="1" />
  </appSettings>
</configuration>

3.patch file

<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0" xdt:Transform="RemoveAttributes(xmlns)" xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform" />

4.nothing happened when I apply the patch to the source.

NPE at XdtDiffWriter: line 409

In the case where there is an element that is missing/was removed from the target instance you are passing a "null" to WriteElement at line 230. This causes an NPE at line 409 when it attempts to access the Parent property.

Use Insert instead of InsertBefore when the delta only exist in target

source file

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
	<startup>
		<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
	</startup>
	<appSettings>
		<add key="test20180421" value="1" />
		<add key="test20180422" value="2" />
	</appSettings>
</configuration>

target file

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <startup>
	  <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
  </startup>
  <appSettings>
	  <add key="test20180421" value="1" />
	  <add key="test20180422" value="2" />
	  <add key="test20180423" value="3" />
	  <add key="test20180424" value="4" />
	</appSettings>
</configuration>

The generated patch file is

<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <appSettings>
    <add key="test20180424" value="4" xdt:Transform="Insert" />
    <add key="test20180423" value="3" xdt:Transform="InsertBefore(/configuration/appSettings/add[(@key='test20180424')])" />
  </appSettings>
</configuration>

The expected format should be, which is good for manually maintain

<?xml version="1.0" encoding="utf-8"?>
<!--For more information on using transformations see the web.config examples at http://go.microsoft.com/fwlink/?LinkId=214134. -->
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
	<appSettings>
		<add key="test20180423" value="3" xdt:Transform="Insert" />
		<add key="test20180424" value="4" xdt:Transform="Insert" />
	</appSettings>
</configuration>

Microsoft.Web.XmlTransform.XmlNodeException: No element in the source document matches

Hi,
I have two xml files
base.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
  <appSettings>
    <add key="test20180421" value="1" />
     <add key="test20180422" value="2" />
  </appSettings>
</configuration>

target.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <appSettings>
      <add key="test20180421" value="1" />
     <add key="test20180423" value="3" />
     <add key="test20180422" value="2" />
  </appSettings>
</configuration>

I got the patch.xml as following

<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0" xdt:Transform="RemoveAttributes(xmlns)" xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <appSettings>
    <add key="test20180423" value="3" xdt:Transform="InsertBefore(/configuration/appSettings/add[(@key='test20180422')])" />
  </appSettings>
</configuration>

when I try to apply the source, I got the exception

Microsoft.Web.XmlTransform.XmlNodeException: No element in the source document matches '/configuration/appSettings/add[(@key='test20180422')]' ---> Microsoft.Web.XmlTransform.XmlTransformationException: No element in the source document matches '/configuration/appSettings/add[(@key='test20180422')]'
at Microsoft.Web.XmlTransform.InsertBase.get_SiblingElement()
at Microsoft.Web.XmlTransform.InsertBefore.Apply()
at Microsoft.Web.XmlTransform.Transform.ApplyOnce()
at Microsoft.Web.XmlTransform.Transform.Execute(XmlElementContext context, String argumentString)
--- End of inner exception stack trace ---
at Microsoft.Web.XmlTransform.XmlTransformationLogger.LogErrorFromException(Exception ex)
at Microsoft.Web.XmlTransform.XmlTransformation.Apply(XmlDocument xmlTarget)
at FatAntelope.CommandLine.Program.Main(String[] args) in E:\GitHub\Other\FatAntelope\FatAntelope.CommandLine\Program.cs:line 104
Microsoft.Web.XmlTransform.XmlTransformationException: No element in the source document matches '/configuration/appSettings/add[(@key='test20180422')]'
at Microsoft.Web.XmlTransform.InsertBase.get_SiblingElement()
at Microsoft.Web.XmlTransform.InsertBefore.Apply()
at Microsoft.Web.XmlTransform.Transform.ApplyOnce()
at Microsoft.Web.XmlTransform.Transform.Execute(XmlElementContext context, String argumentString)

Error when creating Transformed File

Microsoft.Web.XmlTransform.XmlNodeException: 'No element in the source document matches '/configuration/runtime/assemblyBinding/dependentAssembly[27]''

Inner Exception:
XmlTransformationException: No element in the source document matches '/configuration/runtime/assemblyBinding/dependentAssembly[27]

Rename the file extension from .txt to .config and try running the app against the files with the option to generate the transformed file.
Files :
old.txt
new.txt

Error Screenshot :
image

XPath in an InsertBefore transform is using a trait of the parent node that's been transformed into something else

(Side note: This tool is really cool! Out of 160 or so web.configs that I'm diffing from a common base and then applying a transform to as a test, only one of those files broke with this particular issue. Definitely will be a massive time saver for us)

The exception is as follows:

An unhandled exception of type 'Microsoft.Web.XmlTransform.XmlNodeException' occurred in Microsoft.Web.XmlTransform.dll

Additional information: No element in the source document matches '/configuration/system.webServer/rewrite/rules/rule[(@name='Slideshow')]/*[1]'

From what I can see from my quick dig through the source and generated transform, the relevant snippet of the transform that's breaking is:

<!-- ... -->
<rule xdt:Locator="Condition(2)" name="foo" xdt:Transform="SetAttributes(name)">
    <conditions logicalGrouping="MatchAll" xdt:Transform="InsertBefore(/configuration/system.webServer/rewrite/rules/rule[(@name='Slideshow')]/*[1])">
    <!-- ... -->
</rule>
<!-- ... -->

As you can see, it's transforming the name of the <rule> to foo, but then a nested transform has an XPath that's trying to refer to the <rule> by its old name of Slideshow.

I can reproduce this issue with the following files:

base.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <rewrite>
            <rules>
                <rule name="Redirect to https" stopProcessing="true">
                    <match url="(.*)"/>
                    <conditions>
                        <add input="{HTTPS}" pattern="off" ignoreCase="true"/>
                    </conditions>
                    <action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}" redirectType="Permanent"/>
                </rule>
                <rule name="Slideshow" stopProcessing="true">
                    <match url="^s/([^/]*)/([^/]*)(/)?(.*)?" ignoreCase="true"/>
                    <action type="Rewrite" url="slides/page.aspx?view={R:1}&amp;site={R:2}&amp;nav={R:4}"/>
                </rule>
            </rules>
        </rewrite>
    </system.webServer>
</configuration>

target.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <rewrite>
            <rules>
                <rule name="Redirect to https" stopProcessing="true">
                    <match url="(.*)" />
                    <conditions>
                        <add input="{HTTPS}" pattern="off" ignoreCase="true" />
                    </conditions>
                    <action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}" redirectType="Permanent" />
                </rule>

                <rule name="foo" stopProcessing="true">
                  <conditions logicalGrouping="MatchAll">
                    <add input="{HTTP_HOST}" pattern="foo.example.com" negate="false" />
                  </conditions>
                  <action type="Redirect" url="redacted" appendQueryString="false" redirectType="Permanent" />
                </rule>

            </rules>
        </rewrite>
    </system.webServer>
</configuration>

Wrong patch file generated when the attribute has xml namespace

I have the following source file and target file
1.source file

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <runtime>
    <assemblyBinding>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Extensions" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>

2.target file

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.Data.Edm" publicKeyToken="31BF3856AD364E35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-5.6.4.0" newVersion="5.6.4.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>

3.when I generated the patch file,I got this

<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1" xdt:Transform="SetAttributes(xmlns)">
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.Data.Edm" publicKeyToken="31BF3856AD364E35" xdt:Transform="SetAttributes(name,publicKeyToken)" />
        <bindingRedirect oldVersion="0.0.0.0-5.6.4.0" newVersion="5.6.4.0" xdt:Transform="Replace" xmlns="urn:schemas-microsoft-com:asm.v1" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>

4.After applying the patch to source file,I got nothing. The base.xml keep the same as before.

Case error in generated XDT

I have a target file with the following

...
</connectionStrings>
  <location path="." inheritInChildApplications="false">
...

The generated XDT contains the following:

...
<location path="." inheritInChildApplications="false" xdt:Transform="InsertAfter(/configuration/connectionstrings)">
...

Upon attempting to apply the XDT, it fails due to the casing of connectionstrings.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.