Я ищу инструмент сравнения на основе 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>
И, конечно же, все различия должны быть отмечены, желательно рядом с индикаторами или линиями, соединяющими отличающиеся участки.
Бесплатно было бы неплохо.
Необязательное игнорирование пространств имен было бы неплохо.
Технически XML отличаются
но, конечно, вы можете решить игнорировать это или нет, основываясь на семантической информации, которой нет в XML.
Microsoft разработала для этой цели инструмент XML Diff and Patch, и вы можете интегрировать его в свои собственные приложения .
Примечание. Инструмент устанавливается как «Массовая загрузка SQLXML в образце кода .NET» и поставляется с решением Visual Studio XmlDiffView.sln
, которое необходимо скомпилировать самостоятельно. Некоторые базовые знания программирования на C# и Visual Studio Community Edition должны быть в порядке.
Однако, как упоминалось в одном из ответов на Stack Overflow , он был скомпилирован и доступен на Bitbucket .
После этого он поставляется с пользовательским интерфейсом, который позволяет вам выбирать различные параметры сравнения XML:
Когда я применяю его к двум XML-файлам ваших вопросов, возникает исключение. Это из-за пространств имен, которые не определены. После удаления пространств имен пишет:
Сосредоточение внимания на той части, в которой следует сообщать о перемещении разделов как об отсутствии разницы, заставило меня подумать о 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)
Подводя итог, отвечая на ваши требования:
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.
рироуэр
Франк Дернонкур
RockPaperLz - Замаскируй или Шкатулка
Доктор Мойше Пиппик
Джеймс
Ира Бакстер
кнут
Сила Водолея
Мачта
пользователь416
пользователь416