Инструмент Diff для файлов XML?

Я ищу инструмент сравнения на основе Windows, который показывает мне различия между двумя файлами XML, но делает это на основе дерева, а не на основе строк .
Т.е. если раздел переместился в совершенно другое место в файле, он не должен сообщать о различиях.
Эти два файла должны быть отмечены как «одинаковые»:

<soapenv:Body>
  <mes:GetItem>
    <mes:ItemShape>
      <typ:BaseShape>IdOnly</typ:BaseShape>
      <typ:BodyType>Text</typ:BodyType>
      <typ:AdditionalProperties>
        <typ:FieldURI FieldURI="item:Subject" />
        <typ:FieldURI FieldURI="item:Categories" />
      </typ:AdditionalProperties>
    </mes:ItemShape>
    <mes:ItemIds>
      <typ:ItemId Id="AAMYAAA="/>
    </mes:ItemIds>
  </mes:GetItem>
</soapenv:Body>


<soapenv:Body>
  <mes:GetItem>
    <mes:ItemIds>
      <typ:ItemId Id="AAMYAAA="/>
    </mes:ItemIds>
    <mes:ItemShape>
      <typ:BodyType>Text</typ:BodyType>
      <typ:BaseShape>IdOnly</typ:BaseShape>
      <typ:AdditionalProperties>
        <typ:FieldURI FieldURI="item:Categories" />
        <typ:FieldURI FieldURI="item:Subject" />
      </typ:AdditionalProperties>
    </mes:ItemShape>
  </mes:GetItem>
</soapenv:Body>

И, конечно же, все различия должны быть отмечены, желательно рядом с индикаторами или линиями, соединяющими отличающиеся участки.

Бесплатно было бы неплохо.
Необязательное игнорирование пространств имен было бы неплохо.

@rrirower да, но там он был закрыт: / Stack Exchange имеет тенденцию закрываться, а не мигрировать.
Ян, пробовали ли вы самые распространенные программы сравнения в Windows, такие как WinMerge2011, чтобы узнать, есть ли у них опция для этой функции? (Обратите внимание, что WinMerge2011 имеет много обновлений с момента последнего обновления обычного WinMerge, даже если название подразумевает обратное.)
Altova, altova.com/xml_tools.html , представляет собой отличный XML-шпион , который может иметь такую ​​возможность. Текущей бесплатной версии нет, но можно загрузить 30-дневную бесплатную пробную версию. Также см . альтернативу.net /software/altova-xmlspy .
Я мог бы использовать один из них, а также.
«отмечено как« то же самое »» ... Эти XML-файлы являются «одинаковыми» истинными, только если вы настаиваете на том, что порядок некоторых тегов не имеет значения. Для некоторых людей порядок имеет значение. Вам нужна схема или какой-то другой сигнал, чтобы указать, какой случай, для каких тегов.
Beyond Compare имеет специальные функции для XML. Посмотрите Дополнительные форматы файлов для XML.
Я просто подумал, загрузив в память оба файла xml, можно было бы создать даже патч xmlstarlet, потому что в памяти порядок не имеет значения, и каждый элемент будет уникален (в случае дублирования). Если кто-то делает это, пожалуйста, сделайте это на java или, по крайней мере, на совместимом с Linux opensource :)
Спустя 3 года вам случайно не удалось найти решение своей проблемы?
@Mast Моя текущая работа больше не нуждается в этом, поэтому я отложил это на второй план. Тем не менее планирую вернуться к этому посту, когда у меня будет время.

Ответы (6)

Технически XML отличаются

  • если у них есть пробелы или нет
  • если порядок другой
  • если у них есть комментарии или нет
  • есть ли у них инструкции по обработке или нет
  • если их кодировка отличается
  • если их пространства имен различны

но, конечно, вы можете решить игнорировать это или нет, основываясь на семантической информации, которой нет в XML.

Microsoft разработала для этой цели инструмент XML Diff and Patch, и вы можете интегрировать его в свои собственные приложения .

Примечание. Инструмент устанавливается как «Массовая загрузка SQLXML в образце кода .NET» и поставляется с решением Visual Studio XmlDiffView.sln, которое необходимо скомпилировать самостоятельно. Некоторые базовые знания программирования на C# и Visual Studio Community Edition должны быть в порядке.

Однако, как упоминалось в одном из ответов на Stack Overflow , он был скомпилирован и доступен на Bitbucket .

После этого он поставляется с пользовательским интерфейсом, который позволяет вам выбирать различные параметры сравнения XML:

Пользовательский интерфейс XmlDiff

Когда я применяю его к двум XML-файлам ваших вопросов, возникает исключение. Это из-за пространств имен, которые не определены. После удаления пространств имен пишет:

Файлы идентичные для заданных параметров

Спасибо. Я проголосовал за этот ответ, но не отметил его как правильный. Причина: интерфейс окна результатов инструмента с графическим интерфейсом ужасен: при сравнении двух больших файлов XML окно сравнения имеет ширину около 3000 пикселей, содержит все идентичные XML и не имеет полос прокрутки. Затем попробуйте найти различия между двумя файлами по 55 МБ ;-( Я не Cx-программист, поэтому не могу адаптировать программу.
@JanDoggen: да, я согласен, это очень ориентировано на разработчиков. Его вряд ли можно использовать без навыков программирования.
@JanDoggen Полоса прокрутки представляет собой крошечную полоску шириной всего в пару пикселей у правого края окна. Я согласен, что результат не очень красивый, но это все же полезный инструмент.
@ThomasWeller +1 за ссылку на BitBucket. Я скомпилировал, но не повезло, заставив исходный код работать.

Сосредоточение внимания на той части, в которой следует сообщать о перемещении разделов как об отсутствии разницы, заставило меня подумать о https://semanticmerge.com/ , который сравнивает не XML-файлы, а код C# и C. И поскольку он понимает эти языки, он может отображать, если код был перемещен и не изменился.

Это приводит к альтернативному подходу к этому вопросу: возможно ли перевести XML в классы C#, а затем выполнить семантическое слияние полученного кода?

Один из возможных подходов, если этот инструмент еще не написан, может заключаться в переводе каждого элемента в классы и каждого атрибута (и основного текста) в строковое свойство внутри этого класса. Если вы хотите игнорировать пространства имен, пусть ваш переводчик удалит их в процессе перевода.

Я перевел пример XML, приведенный в качестве доказательства концепции, и получил следующее:

class soapenv__Body {
  class mes__GetItem {
    class mes__ItemShape {
      class typ__BaseShape {
          string body="IdOnly";
      }
      class typ__BodyType {
          string body="Textus";
      }
      class typ__AdditionalProperties {
        class typ__FieldURI  {
            string FieldURI="item:Subject";
        }
        class typ__FieldURI  {
            string FieldURI="item:Categories"; 
        }
      }
    }
    class mes__ItemIds {
      class typ__ItemId {
          string Id="AAMYAAA=";
      }
    }
  }
}

Затем я переключил mes:ItemIdsи mes:ItemShapeи изменил текст на Textus. Сравнил следующие два файла в Semantic Merge и получил следующее изображение:

Скриншот семантического слияния

На этом изображении можно увидеть перемещение, обозначенное Mзначком, и изменение текста, обозначенное Cзначком. Линии указывают, где различные части были перемещены/изменены, и можно фактически увидеть различия, если они существуют.

Обратите внимание, что семантическое слияние, хотя и понимает код C#, не ограничивает идентичные имена классов typ__FieldURI, что может быть хорошей функцией, поскольку XML может содержать несколько узлов с одинаковыми именами.

Summa summarum: семантическое слияние может правильно идентифицировать XML как идентичный (или нет), даже если элементы перемещаются, если вы можете преобразовать XML в структуру класса C#.

Ради интереса я попытался переместить typ:FieldUriэлементы, и семантическое слияние правильно определило их как перемещенные. Таким образом, порядок определяется правильно, и вы можете отслеживать порядок атрибутов, если хотите.

Технически это не одно и то же (по крайней мере, в xml), порядок имеет значение, если это явно не указано в схеме.

Комбинация xmlstarlet и обычных линейных утилит может значительно упростить задачу.

Ниже только сравнивается структура, но ее можно расширить, чтобы рассмотреть атрибуты, их значения и текст.

xmlstarlet el snippet1-with-namespaces.xml | sort > structure1.txt

xmlstarlet el snippet2-with-namespaces.xml | sort > structure2.txt

diff structure.txt structure2.txt

После запуска этого на ваших фрагментах diff не показывает различий, но был некоторый текст ошибки о пространствах имен (который можно было бы безопасно игнорировать).

Я бы порекомендовал инструмент XiMpLe , который является основным редактором XML, но он также может сравнивать (и объединять) файлы xml в хорошо организованном порядке. Ваш пример сравнивается и оценивается как идентичный. Существует также возможность разрешать пространства имен.

Пример сравнения результата

В настоящее время я пытаюсь решить довольно похожую проблему для себя. К сожалению, я не нашел ни одной библиотеки, которая бы соответствовала моим потребностям для создания SVG-визуализации сравнения xml.

Поэтому я создал библиотеку с открытым исходным кодом, вдохновленную алгоритмом X-Diff . Так что просто для удовольствия и в надежде найти кого-то, кто поддерживает библиотеку XmlXdiff . До сих пор это не библиотека для проверки пули, и она все еще находится в стадии разработки, но вот результат для вашего примера фрагмента:

введите описание изображения здесь

Код, дающий этот результат:

    from XmlXdiff.XReport import DrawXmlDiff

    _xml1 = """<frame xmlns:soapenv="sn" xmlns:mes="meas" xmlns:typ="type">
    <soapenv:Body>
      <mes:GetItem>
        <mes:ItemShape>
          <typ:BaseShape>IdOnly</typ:BaseShape>
          <typ:BodyType>Text</typ:BodyType>
          <typ:AdditionalProperties>
            <typ:FieldURI FieldURI="item:Subject" />
            <typ:FieldURI FieldURI="item:Categories" />
          </typ:AdditionalProperties>
        </mes:ItemShape>
        <mes:ItemIds>
          <typ:ItemId Id="AAMYAAA="/>
        </mes:ItemIds>
      </mes:GetItem>
    </soapenv:Body>
    </frame>"""
    _xml2 = """<frame xmlns:soapenv="sn" xmlns:mes="meas" xmlns:typ="type">
    <soapenv:Body>
      <mes:GetItem>
        <mes:ItemIds>
          <typ:ItemId Id="AAMYAAA="/>
        </mes:ItemIds>
        <mes:ItemShape>
          <typ:BodyType>Text</typ:BodyType>
          <typ:BaseShape>IdOnly</typ:BaseShape>
          <typ:AdditionalProperties>
            <typ:FieldURI FieldURI="item:Categories" />
            <typ:FieldURI FieldURI="item:Subject" />
          </typ:AdditionalProperties>
        </mes:ItemShape>
      </mes:GetItem>
    </soapenv:Body>
    </frame>"""

    _path1 = '{}\\..\\..\\tests\\simple\\xml1.xml'.format(getPath())
    _path2 = '{}\\..\\..\\tests\\simple\\xml2.xml'.format(getPath())
    _out = '{}\\..\\..\\tests\\simple\\xdiff.svg'.format(getPath())

    with open(_path1, "w") as f:
        f.write(_xml1)

    with open(_path2, "w") as f:
        f.write(_xml2)

    x = DrawXmlDiff(_path1, _path2)
    x.draw()
    x.saveSvg(_out)

Подводя итог, отвечая на ваши требования:

  1. Структурное сравнение, а не линейное сравнение: Да
  2. Может работать в Windows: Да
  3. Беспорядковое сравнение/обработка перемещения: Да
  4. Вывод параллельного сравнения: Да
  5. Игнорирование ожидаемых изменений: Да
  6. Бесплатно: нет, но доступна бесплатная пробная версия.

XML Compare , разработанный DeltaXML, представляет собой структурно-ориентированный инструмент сравнения XML, который можно запускать в Windows , а также в Linux и Mac с использованием Java. Сравнение XML можно использовать через командную строку, REST API и Java API .

Выходные данные сравнения XML Compare представляют собой действительный XML, что означает, что они могут быть легко обработаны другими приложениями и преобразованы в другие форматы вывода с помощью конфигурации постобработки. Изменения идентифицируются добавлением новых атрибутов в вывод diff, которые указывают, присутствовало ли содержимое или структура во входных данных A, присутствовало ли во входных данных B, и были ли они одинаковыми в обоих или изменились. Он соответствует простому формату «A!=B», см. фрагмент кода ниже.

<height deltaxml:deltaV2="A!=B">
           <deltaxml:textGroup deltaxml:deltaV2="A!=B">
              <deltaxml:text deltaxml:deltaV2="A">up to 1.4 meters</deltaxml:text>
              <deltaxml:text deltaxml:deltaV2="B">up to 1.3 meters</deltaxml:text>
           </deltaxml:textGroup>
        </height>

Что касается ваших требований к учету перемещенного содержимого, XML Compare обладает широкими возможностями настройки. Существуют десятки предварительно настроенных входных и выходных процессоров и фильтров, а с помощью XSLT можно создавать собственные конвейеры и фильтры.

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

Наконец, один из доступных предварительно настроенных форматов вывода — это параллельный отчет о различиях в HTML, который строится на дельта-выводе. Однако в тех случаях, когда вам нужен более конкретный вывод, вы можете снова настроить и обработать вывод с помощью XSLT или существующих параметров конфигурации. Ниже приведен скриншот отчета о параллельных различиях:

DeltaXML параллельный отчет о различиях в HTML

Раскрытие информации: я сотрудник DeltaXML.

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