Сравнение XmlDocument для равенства (контент-мудрый)

Если я хочу сравнить содержимое XMlDocument, так ли это?

XmlDocument doc1 = GetDoc1(); XmlDocument doc2 = GetDoc2(); if(doc1 == doc2) { } 

Я не проверяю, являются ли они одной и той же ссылкой на объект, но если СОДЕРЖАНИЕ xml одинаково.

Нет. XmlDocument не переопределяет поведение метода Equals() поэтому на самом деле это просто выполняет ссылочное равенство, которое не будет выполнено в вашем примере, если только документы не являются одним и тем же экземпляром объекта.

Если вы хотите сравнить содержимое (атрибуты, элементы, суммы, PI и т. Д.) Документа, вам придется реализовать эту логику самостоятельно. Будьте осторожны: это не тривиально.

В зависимости от вашего точного сценария вы можете удалить все несущественные пробелы из документа (что само по себе может быть сложным), и они сравнивают полученный XML-текст. Это не идеально – он не подходит для документов, которые семантически идентичны, но отличаются тем, что используются и объявляются пространства имен, а также некоторые escape-последовательности, порядок элементов и т. Д. Как я уже говорил, сравнение XML не является тривиальным.

Вам также необходимо четко определить, что означает, что два документа XML являются «идентичными». Ведется ли упорядочение элементов или атрибутов? Имеет ли смысл (в текстовых узлах) вопрос? Следует ли игнорировать лишние разделы CDATA? Удостоверяются ли инструкции обработки? Что относительно полностью квалифицированных или частично квалифицированных пространств имен?

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

Уже существуют инструменты, которые выполняют различие XML, например Microsoft XML Diff / Patch , вы можете использовать это, чтобы идентифицировать различия между двумя документами. Насколько мне известно, инструмент не распространяется в исходной форме … поэтому, чтобы использовать его во встроенном приложении, вам нужно будет сценарий процесса (если вы планируете его использовать, сначала убедитесь, что условия лицензирования позволяют использовать его и перераспределять ).

EDIT: Отправляйте ответ @Max Toro, если вы используете .NET 3.5 SP1, поскольку, по-видимому, в XLinq есть опция, которая может быть полезна. Приятно знать, что это существует.

Попробуйте метод DeepEquals в API XLinq.

 XDocument doc1 = GetDoc1(); XDocument doc2 = GetDoc2(); if(XNode.DeepEquals(doc1, doc2)) { } 

См. Также Семантика равенства для LINQ to XML Trees

Простым способом может быть сравнение OuterXml .

 var a = new XmlDocument(); var b = new XmlDocument(); a.LoadXml(""); b.LoadXml(""); Debug.Assert(a.OuterXml == b.OuterXml); 

Л.Бушкин прав, это не тривиально. Поскольку XML – это строковые данные, вы можете технически выполнить hash содержимого и сравнить их, но на это будут влиять такие вещи, как пробелы.

Вы можете выполнить структурированный diff (также называемый «XML diffgram») между двумя документами и сравнить результаты. Например, такие данные .NET отслеживают изменения.

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

Часто вы хотите сравнить строки XML, упорядоченные по-разному. Это легко сделать с помощью этого кода

 class Testing { [Test] public void Test() { Assert.AreEqual( "".SortXml() , "".SortXml()); } } public static class XmlCompareExtension { public static string SortXml(this string @this) { var xdoc = XDocument.Parse(@this); SortXml(xdoc); return xdoc.ToString(); } private static void SortXml(XContainer parent) { var elements = parent.Elements() .OrderBy(e => e.Name.LocalName) .ToArray(); Array.ForEach(elements, e => e.Remove()); foreach (var element in elements) { parent.Add(element); SortXml(element); } } }