XmlDiffPatch вызывает исключение Длина не может быть меньше нуля

Я создаю сценарий механизма сравнения в PowerShell, и одна из вещей, которые мне нужно для сравнения - это XML-файлы. Когда я использую нативный объект-объект powershell, он возвращает 0 различий, если я получаю externalxml (текстовое представление) и diff, в котором я получаю различия. к сожалению, это помещает все в одну длинную строку, поэтому это бесполезно.

Затем я попытался использовать библиотеку XmlDiffPatch от Microsoft, однако, если я использую программу-пример или библиотеку в powershell, мои 2 xml-файла терпят неудачу за исключением:

$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

Без доступа к исходному коду для этой библиотеки я понятия не имею, что происходит, кроме ошибки. 2 разбора XML хорошо в IE, так что я знаю, что они действительны XML.

Кто-нибудь еще видел это раньше? Как ты это решил?

4 ответа

Похоже, в библиотеке XMLDiffPatch есть ошибка в методе Microsoft.XmlDiffPatch.XmlDiff.NormalizeText(String text), который не может обрабатывать строки, содержащие только пробелы (" "). Если вы его передадите, метод попытается создать экземплярstring отрицательной длины, следовательно, исключение.

Некоторые из моих XML, которые я сравнивал, содержат атрибуты, такие как AttributeName=" ", и они вызывали эти исключения, когда библиотека пыталась их нормализовать. Я просмотрел спецификацию XML, и такие атрибуты не запрещены.

Оказывается, это нельзя исправить, и нет хорошего обходного пути (кроме "исправления" XML перед сравнением). Вместо этого я использовал библиотеку XmlUnit.Net.

Вот способ, которым я использую это и полный пример для людей, которые хотят обнаружить это:

# 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();

куда M1.xml а также M2.xml два похожих или отличающихся файла XML M3.xml получит дельту.

Пакет для использования в 2022 г. +: https://www.nuget.org/packages/LovettSoftware.XmlDiff
. Совместим с современными версиями .NET (NETStandard2.0, NET6+, даже .NET 4.5.2).

Это взято из официального репозитория Microsoft XmlNotepad.

Для людей, которые столкнулись с этим (как и я), источник XmlDiffPatch вместе с исправлением этой проблемы доступен здесь: - https://github.com/shadolight/XmlDiffPatch

Не мое репо просто ищет то же решение.

Другие вопросы по тегам