Каков наилучший способ сравнить файлы XML на равенство? - PullRequest
12 голосов
/ 18 ноября 2008

Я использую .NET 2.0, и недавнее изменение кода аннулировало мой предыдущий вызов Assert.AreEqual (который сравнивал две строки XML). Только новый элемент XML фактически отличается в новой кодовой базе, поэтому я надеюсь, что сравнение всех других элементов даст мне желаемый результат. Сравнение необходимо проводить программно, так как оно является частью модульного теста.

Сначала я рассматривал возможность использования нескольких экземпляров XmlDocument. Но потом я нашел это: http://drowningintechnicaldebt.com/blogs/scottroycraft/archive/2007/05/06/comparing-xml-files.aspx

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

Я бы не хотел добавлять еще одну зависимость для этого, если это вообще возможно.

Похожие вопросы

Ответы [ 6 ]

10 голосов
/ 18 ноября 2008

Это действительно зависит от того, что вы хотите проверить как «различия».

Сейчас мы используем Microsoft XmlDiff: http://msdn.microsoft.com/en-us/library/aa302294.aspx

4 голосов
/ 18 ноября 2008

Может показаться, что анализировать XML в XmlDocument и основывать ваши вызовы Assert на XPath Query менее хрупко. Вот некоторые вспомогательные методы утверждения, которые я часто использую. Каждый из них использует XPathNavigator, который можно получить, вызвав CreateNavigator () для XmlDocument или на любом узле, полученном из документа. Пример использования будет:

     XmlDocument doc = new XmlDocument( "Testdoc.xml" );
     XPathNavigator nav = doc.CreateNavigator();
     AssertNodeValue( nav, "/root/foo", "foo_val" );
     AssertNodeCount( nav, "/root/bar", 6 )

    private static void AssertNodeValue(XPathNavigator nav,
                                         string xpath, string expected_val)
    {
        XPathNavigator node = nav.SelectSingleNode(xpath, nav);
        Assert.IsNotNull(node, "Node '{0}' not found", xpath);
        Assert.AreEqual( expected_val, node.Value );
    }

    private static void AssertNodeExists(XPathNavigator nav,
                                         string xpath)
    {
        XPathNavigator node = nav.SelectSingleNode(xpath, nav);
        Assert.IsNotNull(node, "Node '{0}' not found", xpath);
    }

    private static void AssertNodeDoesNotExist(XPathNavigator nav,
                                         string xpath)
    {
        XPathNavigator node = nav.SelectSingleNode(xpath, nav);
        Assert.IsNull(node, "Node '{0}' found when it should not exist", xpath);
    }

    private static void AssertNodeCount(XPathNavigator nav, string xpath, int count)
    {
        XPathNodeIterator nodes = nav.Select( xpath, nav );
        Assert.That( nodes.Count, Is.EqualTo( count ) );
    }
1 голос
/ 29 апреля 2016

Я написал небольшую библиотеку с утверждениями для сериализации, source .

Образец:

[Test]
public void Foo()
{
   ...
   XmlAssert.Equal(expected, actual, XmlAssertOptions.IgnoreDeclaration | XmlAssertOptions.IgnoreNamespaces);
}

NuGet

1 голос
/ 18 ноября 2008

Сравнение простой строки для строки xml не всегда работает. Почему?

например, оба:

<MyElement></MyElmennt> и <MyElment/> равны с xml точки зрения.

Существуют алгоритмы преобразования, заставляющие xml всегда выглядеть одинаково, они называются алгоритмы канонизации. .Net имеет поддержку канонизации.

0 голосов
/ 20 ноября 2008

Я получил желаемый результат со следующим кодом:

private static void ValidateResult(string validationXml, XPathNodeIterator iterator, params string[] excludedElements)
    {
        while (iterator.MoveNext())
        {
            if (!((IList<string>)excludedElements).Contains(iterator.Current.Name))
            {
                Assert.IsTrue(validationXml.Contains(iterator.Current.Value), "{0} is not the right value for {1}.", iterator.Current.Value, iterator.Current.Name);
            }
        }
    }

Перед вызовом метода я создаю навигатор для экземпляра XmlDocument следующим образом:

XPathNavigator nav = xdoc.CreateNavigator();

Далее я создаю экземпляр XPathExpression, например так:

XPathExpression expression = XPathExpression.Compile("/blah/*");

Я вызываю метод после создания итератора с выражением:

XPathNodeIterator iterator = nav.Select(expression);

Я все еще выясняю, как оптимизировать его дальше, но пока он работает.

0 голосов
/ 19 ноября 2008

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

Как правило, вы должны создать класс, который определяет ваши правила равенства и использовать его для ваших сравнений, и если ваш класс сравнения реализует интерфейсы IEqualityComparer and/or IEqualityComparer<T>, то ваш класс можно использовать в связке встроенных списков фреймворков в качестве теста на равенство реализация также. Плюс, конечно, вы можете иметь столько, сколько вам нужно, чтобы измерить равенство по-разному, как того требуют ваши требования.

т.е.

IEnumerable<T>.Contains
IEnumerable<T>.Equals
The constructior of a Dictionary etc etc
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...