Как бы вы сравнили два XML-документа? - PullRequest
58 голосов
/ 03 октября 2008

Как часть базового класса для некоторого расширенного модульного тестирования, я пишу вспомогательную функцию, которая рекурсивно сравнивает узлы одного объекта XmlDocument с другим в C # (.NET). Некоторые требования этого:

  • Первым документом является источник , например как я хочу, чтобы XML-документ выглядел. Таким образом, второй - это тот, в котором я хочу найти различия, и он не должен содержать лишних узлов, отсутствующих в первом документе.
  • Должен выдать исключение, если обнаружено слишком много существенных различий, и это должно быть легко понято человеком, взглянувшим на описание.
  • Важен порядок дочерних элементов, атрибуты могут быть в любом порядке.
  • Некоторые атрибуты игнорируются; в частности xsi:schemaLocation и xmlns:xsi, хотя я бы хотел указать, какие из них.
  • Префиксы для пространств имен должны совпадать как по атрибутам, так и по элементам.
  • Пробел между элементами не имеет значения.
  • Элементы будут либо иметь дочерние элементы или InnerText, но не оба.

Пока я что-то записываю: кто-нибудь написал такой код и можно ли поделиться им здесь?

Кроме того, как бы вы назвали первый и второй документы? Я называю их «источником» и «целью», но это неправильно, поскольку source - это то, что я хочу, чтобы target выглядело как-то иначе, иначе я выбрасываю исключение .

Ответы [ 12 ]

53 голосов
/ 03 октября 2008

Microsoft имеет XML diff API , который вы можете использовать

5 голосов
/ 23 ноября 2011

try XMLUnit . Эта библиотека доступна как для Java, так и для .Net

5 голосов
/ 03 октября 2008

Сравнение XML-документов является сложным. Google для xmldiff (есть даже решение Microsoft) для некоторых инструментов. Я решил это несколькими способами. Я использовал XSLT для сортировки элементов и атрибутов (потому что иногда они появлялись в другом порядке, и мне было все равно), и отфильтровывал атрибуты, которые я не хотел сравнивать, а затем либо использовал XML :: Diff или XML :: SemanticDiff модуль perl, или просто печатать каждый документ с каждым элементом и атрибутом в отдельной строке, и используя Unix командной строки diff по результатам.

4 голосов
/ 05 мая 2015

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

public bool XMLCompare(XElement primary, XElement secondary)
{
    if (primary.HasAttributes) {
        if (primary.Attributes().Count() != secondary.Attributes().Count())
            return false;
        foreach (XAttribute attr in primary.Attributes()) {
            if (secondary.Attribute(attr.Name.LocalName) == null)
                return false;
            if (attr.Value.ToLower() != secondary.Attribute(attr.Name.LocalName).Value.ToLower())
                return false;
        }
    }
    if (primary.HasElements) {
        if (primary.Elements().Count() != secondary.Elements().Count())
            return false;
        for (var i = 0; i <= primary.Elements().Count() - 1; i++) {
            if (XMLCompare(primary.Elements().Skip(i).Take(1).Single(), secondary.Elements().Skip(i).Take(1).Single()) == false)
                return false;
        }
    }
    return true;
}
3 голосов
/ 07 ноября 2015

https://github.com/CameronWills/FatAntelope Еще одна альтернативная библиотека для Microsoft XML Diff API. Он имеет алгоритм XML-различий, позволяющий выполнять неупорядоченное сравнение двух XML-документов и обеспечивать оптимальное соответствие.

Это порт C # алгоритма X-Diff, описанного здесь: http://pages.cs.wisc.edu/~yuanwang/xdiff.html

Отказ от ответственности : Я написал это:)

3 голосов
/ 16 ноября 2009

Я использую ExamXML для сравнения файлов XML. Можешь попробовать. Авторы, A7Soft, также предоставляют API для сравнения XML-файлов

2 голосов
/ 20 декабря 2018

Для сравнения двух выходных XML-данных в автоматическом тестировании я нашел XNode.DeepEquals.

Сравнивает значения двух узлов, включая значения всех узлов-потомков.

Использование:

var xDoc1 = XDocument.Parse(xmlString1);
var xDoc2 = XDocument.Parse(xmlString2);

bool isSame = XNode.DeepEquals(xDoc1.Document, xDoc2.Document);
//Assert.IsTrue(isSame);

Ссылка: https://docs.microsoft.com/en-us/dotnet/api/system.xml.linq.xnode.deepequals?view=netcore-2.2

2 голосов
/ 01 сентября 2013

Не относится к OP, поскольку в данный момент он игнорирует дочерний порядок, но если вам нужно решение только с кодом, вы можете попробовать XmlSpecificationCompare , который я несколько ошибочно разработал.

2 голосов
/ 30 августа 2010

Еще один способ сделать это -

  1. Получить содержимое обоих файлов в две разные строки.
  2. Преобразуйте строки, используя XSLT (который просто скопирует все в две новые строки). Это обеспечит удаление всех пробелов за пределами элементов. Это приведет к двум новым строкам.
  3. Теперь просто сравните две строки друг с другом.

Это не даст вам точное местоположение разницы, но если вы просто хотите узнать, есть ли различие, это легко сделать без каких-либо сторонних библиотек.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...