Ответ 1
У Microsoft есть XML diff API, который вы можете использовать.
Неофициальный NuGet: https://www.nuget.org/packages/XMLDiffPatch.
Как часть базового класса для некоторого обширного модульного тестирования, я пишу вспомогательную функцию, которая рекурсивно сравнивает узлы одного объекта XmlDocument с другим в С# (.NET). Некоторые требования:
xsi:schemaLocation
и xmlns:xsi
, хотя я хотел бы иметь возможность передать, в каких из них.InnerText
, но не оба.Пока я разбираю что-то вместе: кто-нибудь написал такой код, и можно ли его разделить здесь?
В стороне, что бы вы назвали первым и вторым документами? Я упоминал их как "источник" и "цель", но он чувствует себя не так, поскольку источник - это то, что я хочу, чтобы target выглядел, иначе я бросаю исключение.
У Microsoft есть XML diff API, который вы можете использовать.
Неофициальный NuGet: https://www.nuget.org/packages/XMLDiffPatch.
Я погуглил более полный список решений этой проблемы сегодня, я собираюсь попробовать одно из них скоро:
Сравнение документов XML сложнее. Google для xmldiff (там даже решение Microsoft) для некоторых инструментов. Я решил это несколькими способами. Я использовал XSLT для сортировки элементов и атрибутов (потому что иногда они появлялись в другом порядке, и меня это не волновало) и отфильтровывали атрибуты, которые я не хотел сравнивать, а затем либо использовали XML:: Diff или XML:: SemanticDiff perl module, или довольно печатайте каждый документ с каждым элементом и атрибутом на отдельной строке и используя разницу в командной строке Unix для результатов.
попробуйте XMLUnit. Эта библиотека доступна как для Java, так и для .Net
Этот код не удовлетворяет всем вашим требованиям, но он прост, и я использую его для своих модульных тестов. Порядок атрибутов не имеет значения, но порядок элементов имеет значение. Элемент внутреннего текста не сравнивается. Я также проигнорировал случай при сравнении атрибутов, но вы можете легко удалить это.
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;
}
Я использую ExamXML для сравнения файлов XML. Можешь попробовать. Авторы A7Soft также предоставляют API для сравнения файлов XML
https://github.com/CameronWills/FatAntelope Другая альтернативная библиотека API XML Diff API. Он имеет XML-алгоритм, который выполняет неупорядоченное сравнение двух документов XML и обеспечивает оптимальное соответствие.
Это порт С# описанного здесь алгоритма X-Diff: http://pages.cs.wisc.edu/~yuanwang/xdiff.html
Отказ от ответственности: я написал это:)
Другой способ сделать это -
Это не даст вам точное местоположение разницы, но если вы просто хотите знать, есть ли разница, это легко обойтись без каких-либо сторонних библиотек.
Не относится к OP, так как в данный момент он игнорирует дочерний порядок, но если вы хотите только решение для кода, вы можете попробовать XmlSpecificationCompare, который я несколько ошибочно разработано.
Для сравнения двух выходных 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
На основе @Two Cents ответьте и используйте эту ссылку XMLSorting я создал свой собственный XmlComparer
Сравнить XML-программу
private static bool compareXML(XmlNode node, XmlNode comparenode)
{
if (node.Value != comparenode.Value)
return false;
if (node.Attributes.Count>0)
{
foreach (XmlAttribute parentnodeattribute in node.Attributes)
{
string parentattributename = parentnodeattribute.Name;
string parentattributevalue = parentnodeattribute.Value;
if (parentattributevalue != comparenode.Attributes[parentattributename].Value)
{
return false;
}
}
}
if(node.HasChildNodes)
{
sortXML(comparenode);
if (node.ChildNodes.Count != comparenode.ChildNodes.Count)
return false;
for(int i=0; i<node.ChildNodes.Count;i++)
{
string name = node.ChildNodes[i].LocalName;
if (compareXML(node.ChildNodes[i], comparenode.ChildNodes[i]) == false)
return false;
}
}
return true;
}
Сортировка XML-программы
private static void sortXML(XmlNode documentElement)
{
int i = 1;
SortAttributes(documentElement.Attributes);
SortElements(documentElement);
foreach (XmlNode childNode in documentElement.ChildNodes)
{
sortXML(childNode);
}
}
private static void SortElements(XmlNode rootNode)
{
for(int j = 0; j < rootNode.ChildNodes.Count; j++) {
for (int i = 1; i < rootNode.ChildNodes.Count; i++)
{
if (String.Compare(rootNode.ChildNodes[i].Name, rootNode.ChildNodes[1 - 1].Name) < 0)
{
rootNode.InsertBefore(rootNode.ChildNodes[i], rootNode.ChildNodes[i - 1]);
}
}
}
// Console.WriteLine(j++);
}
private static void SortAttributes(XmlAttributeCollection attribCol)
{
if (attribCol == null)
return;
bool changed = true;
while (changed)
{
changed = false;
for (int i = 1; i < attribCol.Count; i++)
{
if (String.Compare(attribCol[i].Name, attribCol[i - 1].Name) < 0)
{
//Replace
attribCol.InsertBefore(attribCol[i], attribCol[i - 1]);
changed = true;
}
}
}
}
Я написал этот сравнительный лист на основе XSLT 1.0, в котором вы сравниваете b.xml с входным xml, выводя различия элементов на входе, которых нет в b.xml.