我正在检查string给出的两个XML元素是否与此方法相同:
private static bool XmlEquals(string s1, string s2)
{
return XNode.DeepEquals(XElement.Parse(s1), XElement.Parse(s2));
}
除非其中一个元素具有开始和结束标记,另一个元素具有如下所示的闭合标记,否则此工作将起作用:
<MyElement SomeAttribute="some value" />
<MyElement SomeAttribute="some value"></MyElement>
我能否以某种方式比较两个XML元素,上述情况被视为相等?
答案 0 :(得分:2)
解决此特定问题的直接方法是introduce closing brackets explicitly:
private static bool XmlEquals(string s1, string s2)
{
var firstElement = XElement.Parse(s1);
var secondElement = XElement.Parse(s2);
IntroduceClosingBracket(firstElement);
IntroduceClosingBracket(secondElement);
return XNode.DeepEquals(firstElement, secondElement);
}
private static void IntroduceClosingBracket(XElement element)
{
foreach (var descendant in element.DescendantsAndSelf())
{
if (descendant.IsEmpty)
{
descendant.SetValue(String.Empty);
}
}
}
但是,遍历所有后代可能会导致性能下降。
答案 1 :(得分:1)
如果XML不必完全相同,就像在@ defaultlocale的解决方案中真正比较所有内容(甚至评论)一样,你可以使用LINQ
来比较你感兴趣的东西。为了表明我的想法ve使属性值的比较可选。
测试数据:
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>";
递归比较:
// 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;
}
答案 2 :(得分:-1)
存在一个空标签时使用XNode.DeepEquals的问题, 比较XML文档中所有XML元素的最佳方法(即使XML结束标记不同,这也应该起作用)
public bool CompareXml()
{
var doc = @"
<ContactPersons>
<ContactPersonRole>General</ContactPersonRole>
<Person>
<Name>Aravind Kumar Eriventy</Name>
<Email/>
<Mobile>9052534488</Mobile>
</Person>
</ContactPersons>";
var doc1 = @"
<ContactPersons>
<ContactPersonRole>General</ContactPersonRole>
<Person>
<Name>Aravind Kumar Eriventy</Name>
<Email></Email>
<Mobile>9052534488</Mobile>
</Person>
</ContactPersons>";
return XmlDocCompare(XDocument.Parse(doc), XDocument.Parse(doc1));
}
private static bool XmlDocCompare(XDocument doc,XDocument doc1)
{
IntroduceClosingBracket(doc.Root);
IntroduceClosingBracket(doc1.Root);
return XNode.DeepEquals(doc1, doc);
}
private static void IntroduceClosingBracket(XElement element)
{
foreach (var descendant in element.DescendantsAndSelf())
{
if (descendant.IsEmpty)
{
descendant.SetValue(String.Empty);
}
}
}
答案 3 :(得分:-5)
您始终可以将字符串拆分为引号,然后进行比较。
s1Array = s1.Split('\"');
s2Array = s2.Split('\"');
if(s1[0] == s2[0] && s1[1] == s2[1])
return true;
忽略空值就像检查
一样简单if(s1[1] == String.Empty || s1[1] == null)...