Jeśli XML nie musi być dokładnie taki sam jak w rozwiązaniu @ defaultlocale, które naprawdę porównuje wszystko (nawet komentarze), można użyć LINQ
, aby porównać tylko te rzeczy, które są zainteresowane. Aby pokazać pomysł zrobiłem porównanie wartości atrybutów opcjonalne. Dane
Test:
var xml1 = @"
<elm1 attr1='val1'>
<elm2 attr2='val1'>
<elm3 attr3='val1' />
</elm2>
</elm1>";
var xml2 = @"
<elm1 attr1='val1'>
<elm2 attr2='val1'>
<elm3 attr3='val1' attr='val2' />
</elm2>
</elm1>";
rekurencyjne porównanie:
// Just a helper.
private static Tuple<XElement, XElement> Compare(
string xml1,
string xml2,
bool compareAttributeValues)
{
return Compare(
XElement.Parse(xml1),
XElement.Parse(xml2),
compareAttributeValues);
}
// Compares XElements recursively
// and returns the two nodes that are different if any.
private static Tuple<XElement, XElement> Compare(
XElement xElm1,
XElement xElm2,
bool compareAttributeValues)
{
// Elements are different if they have a different number of children.
if (xElm1.Elements().Count() != xElm2.Elements().Count())
{
return new Tuple<XElement, XElement>(xElm1, xElm2);
}
// Enumerate both elements at the same time.
var elements = Enumerable.Zip(
xElm1.Elements(),
xElm2.Elements(),
(x, y) => new Tuple<XElement, XElement>(x, y));
foreach (var item elements)
{
// Elements are equal if they have the same names...
bool haveSameNames = xElm1.Name.LocalName == xElm2.Name.LocalName;
// and the same attributes.
bool haveSameAttributes =
item.Item1
// Concatenate and group attributes by their name.
.Attributes()
.Concat(item.Item2.Attributes())
.GroupBy(x => x.Name.LocalName, (key, items) => new
{
Name = key,
Items = items,
// Attiribute value comparison can be skipped.
// If enabled compare attribute values.
// They are equal if the result is only one group.
HaveSameValues =
compareAttributeValues == false
|| items.GroupBy(y => y.Value).Count() == 1,
Count = items.Count()
})
// Each attribute group must contain two items
// if they are identical (one per element).
.Where(x => x.Count != 2 || x.HaveSameValues == false)
.Any() == false;
if (!haveSameNames || !haveSameAttributes)
{
return item;
}
else
{
// Return the different nodes.
return Compare(item.Item1, item.Item2, compareAttributeValues);
}
}
// No differences found.
return null;
}
Czy spróbować porównać je jako ciąg? –
Myślę, że trzeba poszukać implementacji drzewa niż przechodzić przez sprawdzanie węzłów: http://msdn.microsoft.com/en-us/library/bb348073%28v=vs.110%29.aspx – LordTitiKaka
To pytanie wydaje się mieć podobne, jeśli nie równe, różnice semantyczne: http://stackoverflow.com/questions/7318157/best-way-to-compare-xelement-objects –