Программный XML Diff/Merge в С#

В данный момент я управляю частью программного обеспечения, имеющего несколько файлов конфигурации XML. Когда выпущена новая версия программного обеспечения, иногда файлы базовых конфигураций меняются, в настоящее время мы запускаем программный вызов KDiff при запуске. Если он обнаруживает изменение, он предлагает пользователю выбрать изменения.

Проблема с этим подходом заключается в том, что KDiff - это программа сравнения строк и не знает пути XML (например, узлы и т.д.).

В идеале я хотел бы программно работать с библиотекой на С# (так как мы являемся магазином MS), который может Diff два файла XML: исходный XML и текущий рабочий XML.

И затем объедините их вместе с помощью нескольких простых правил:

  • Если текущий рабочий XML имеет node, который отсутствует в исходном XML файле, удалите его.
  • Если исходный XML имеет node, который не поддерживает текущий рабочий XML, добавьте его.
  • Если оба имеют одинаковый node и значения различаются, используйте значение Source XML, если только значение исходного XML не установлено на "UseExistingValue".

Например, здесь "Источник" XML:

<Configuration>
  <Items>
     <Item Id="1" Position="true">
       <Location X="UseExistingValue" Y="UseExistingValue" Z="UseExistingValue" />

       <Something/>
       <SomethingElse/>
     </Item>
   </Items>
 </Configuration>

И здесь "Текущий рабочий" XML:

<Configuration>
  <Items>
    <Item Id="1" Position="false">
      <Location X="123" Y="234" Z="345" />
      <Another/>
      <Something/>

    </Item>
  </Items>
</Configuration>

И объединенная версия будет выглядеть так:

<Configuration>
  <Items>
    <Item Id="1" Position="true">
      <Location X="123" Y="234" Z="345" />

      <Something/>
      <SomethingElse/>
    </Item>
  </Items>
</Configuration>

Я просмотрел MS Diff и Patch Tool, и он определенно объединяет файлы вместе, но не позволяет программным правила, которые я хочу определить.

XMLUnit для Java-разработчиков кажется многообещающим, но версия .NET выглядит слаборазвитой, что является неудачным.

У кого-нибудь есть предложения для скриптовых инструментов XML Diff/Merge и/или .NET-библиотек (платных или бесплатных)?

Спасибо.

Ответы

Ответ 1

После нескольких дней беспорядков я нашел решение, которое, как мне кажется, работает для меня. Возможно, это может сработать и для других людей.

Средство MS Diff и Patch было жизнеспособным вариантом. Когда вы Diff первый файл со вторым файлом, он создает XML "DiffGram", в котором перечисляются изменения, которые он обнаружил между двумя файлами XML.

Чтобы позаботиться обо всех трех правилах, перечисленных выше, я выполнил два файла в одном направлении, затем открыл файл DiffGram с использованием Linq-to-XML и удалил все строки "Добавить" и "Удалить".

XNamespace xd = "http://schemas.microsoft.com/xmltools/2002/xmldiff";
var doc = XDocument.Load(_diffGramFile);
doc.Root.DescendantsAndSelf(xd + "add").Remove();
doc.Root.DescendantsAndSelf(xd + "remove").Remove();

Затем я закрепил (объединил) этот отредактированный diffgram против первого файла и создал частично объединенный временный файл. Это позаботится о правилах 1 и 2.

Далее, я Diff'd частично объединенный файл против первого используемого файла. Затем открыли новый DiffGram и удалили все ссылки на ссылку "UseExistingValue".

var newdoc = XDocument.Load(_diffGramFile);
newdoc.Root.DescendantsAndSelf(xd + "change")
      .Where(x => x.Value == "UseExistingValue").Remove();

И объединил этот отредактированный DiffGram с частично объединенным файлом, который заботится о правиле 3. Сохранение этого в XML затем приводит к окончательному объединению XML в соответствии с правилами, определенными выше.

Надеюсь, это поможет другим людям.

СОВЕТ. После установки библиотеки XmlDiffPatch библиотеку XmlDiffPatch можно найти в C:\Windows\assembly\GAC\XmlDiffPatch\1.0.8.28__b03f5f7f11d50a3a\XmlDiffPatch.dll