Подтвердить что ты не робот

Каков наилучший способ сравнить файлы XML для равенства?

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

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

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

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

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

4b9b3361

Ответ 2

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

     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 ) );
    }

Ответ 3

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

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

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

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

Ответ 4

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

Пример:

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

NuGet

Ответ 5

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

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

i.e

IEnumerable<T>.Contains
IEnumerable<T>.Equals
The constructior of a Dictionary etc etc

Ответ 6

В итоге я получил результат, который мне нужен, со следующим кодом:

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);

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