检查XML元素是否等于另一个XML元素,忽略空值

时间:2015-01-08 13:09:06

标签: c# xml

我正在检查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元素,上述情况被视为相等

4 个答案:

答案 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)...