Reputation: 1503
I am building a comparison engine script in PowerShell and one of the things I need to be able to compare are XML files. When I use the native PowerShell compare-object it returns 0 differences, yet if I grab the outerxml (text representation) and diff that I do get differences. Unfortunately this puts everything into one long string so is not useful.
I then tried using the XmlDiffPatch library from Microsoft, however if I use the sample program or the library within PowerShell, my 2 XML files fail with the exception:
$d.Compare("c:\scripts\ps\ref.xml", "c:\scripts\ps\tgt.xml", $false)
Exception calling "Compare" with "3" argument(s): "Length cannot be less than zero.
Parameter name: length"
At line:1 char:1
+ $d.Compare("c:\scripts\ps\ref.xml", "c:\scripts\ps\tgt.xml", $false)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ArgumentOutOfRangeException
Without access to the source code for this library I have no idea what is going on other than a bug. The 2 XML's parse fine in IE, so I know they are valid XML.
Has anyone else seen this before? How did you solve it?
Upvotes: 0
Views: 1062
Reputation: 103
The package to use in 2022+: https://www.nuget.org/packages/LovettSoftware.XmlDiff
Compatible with modern .NET versions (NETStandard2.0, NET6+, even .NET 4.5.2)
It's coming from the official Microsoft XmlNotepad repo
Upvotes: 0
Reputation: 915
For Folks who come across this (like I did) source for XmlDiffPatch along with a fix for this issue is available here: - https://github.com/shadolight/XmlDiffPatch
Not my repo just looking for the same solution.
Upvotes: 0
Reputation: 11
Looks like XMLDiffPatch library has a bug in its method Microsoft.XmlDiffPatch.XmlDiff.NormalizeText(String text)
, which can't handle whitespace-only strings (" "
). If you pass one, the method tries to instantiate a string
of negative length, hence the exception.
Some of my XML's I was comparing contained attributes like AttributeName=" "
, and they were causing these exceptions when the library tried to normalize them. I glanced over the XML spec, and attributes like this are not forbidden.
Turns out it can't be fixed, and there's no good workaround (except for 'fixing' XML prior to comparison). I ended up using XmlUnit.Net library instead.
Upvotes: 1
Reputation: 72660
Here is a way I use it and a complete example for people who want to discover it :
# Test-xmldiffpatch.ps1
# This code need to download Microsoft tool
# https://msdn.microsoft.com/en-us/library/aa302294
# or Nuget
# https://www.nuget.org/packages/XMLDiffPatch/
# Load the external DLL
Add-Type -Path "C:\Program Files (x86)\XmlDiffPatch\Bin\xmldiffpatch.dll"
$xmlD1=[XML](Get-Content 'd:\temp\M1.xml')
$xmlD2=[XML](Get-Content 'd:\temp\M2.xml')
$xmlWriter = [System.Xml.XmlWriter]::Create("d:\temp\M3.xml")
$xmlDiff= New-Object Microsoft.XmlDiffPatch.XmlDiff
$xmlDiff.IgnorePrefixes=$true
$xmlDiff.IgnoreChildOrder=$true
$xmlDiff.IgnoreNamespaces=$true
$blIdentical = $xmldiff.Compare($xmlD1, $xmlD2, $xmlWriter);
$blIdentical
$xmlWriter.Close();
Where M1.xml
and M2.xml
are two similars or differents XML file M3.xml
will receive the delta.
Upvotes: 1