如何检查不同XML文件中包含的XML节点是否相等?

时间:2018-09-13 18:40:32

标签: c# .net xml

我有两个使用System.Xml.XmlDocument.LoadXml(fileName)方法读取的XML文件(文件A和文件B,其中文件A是文件B的子集)。

然后我要使用System.Xml.XmlNode.SelectNodes(nodeName)在这些文件中选择节点,我需要比较文件A中每个选定的xml节点是否相等或文件B中相同节点的子集。还需要检查文件A中任何节点内包含的子节点的顺序与文件B中该节点内包含的相同子节点的顺序相同。

例如,

文件A

<rootNodeA>
 <elementA>
  <subelementA>content</subElementA>
  <subelementB>content</subElementB>
  <subelementB>content</subElementC>
  <subelementB>content</subElementD>
 </elementA>
 <elementB>
  <subelementA>content</subElementA>
  <subelementB>content</subElementB>
 </elementB>
</rootNodeA>

文件B

<rootNodeB>
 <elementA>
  <subelementB>content</subElementB>
  <subelementD>content</subElementD>
 </elementA>
 <elementB>
  <subelementA>content</subElementA>
 </elementB>
</rootNodeB>

如您所见,fileB是fileA的子集。我需要检查文件B的elementA节点是否等于文件A中同一elementA节点的子集。对于子节点(subElementA等),这应该是正确的,因为以及节点/子节点的内容。

此外,如果您在文件A中看到elementA,则按照A,B,C,D的顺序有4个子元素。对于文件B中相同的elementA,按A,D顺序有2个子元素。此顺序,即A在D之前排在D之前,与文件A中的顺序相同,同样需要检查。

我的想法是计算节点的哈希值,然后比较它们,但不确定如何或是否可以满足目的。

编辑:我到目前为止拥有的代码,

    HashSet<XmlElement> hashA = new HashSet<XmlElement>();
    HashSet<XmlElement> hashB = new HashSet<XmlElement>();

                foreach (XmlElement node in nodeList)
                {
                    hashA.Add(node);
                }
                foreach(XmlElement node in masterNodeList)
                {
                    hashB.Add(node);
                }
                isSubset = new HashSet<XmlElement>(hashA).IsSubsetOf(hashB);
            return isSubset;

1 个答案:

答案 0 :(得分:0)

这听起来像一个简单的递归函数。

没有检查它是否真正起作用,但这应该可以做到:

public static bool isSubset(XmlElement source, XmlElement target)
    {
        if (!target.HasChildNodes)
        {
            if (source.HasChildNodes) // surly not same.
                return false;
            return string.Equals(source.Value, target.Value); // equalize values.
        }

        var sourceChildren = source.ChildNodes.OfType<XmlElement>().ToArray(); // list all child tags in source (by order)
        var currentSearchIndex = 0; // where are we searching from (where have we found our match)

        foreach (var targetChild in target.ChildNodes.OfType<XmlElement>())
        {
            var findIndex = Array.FindIndex(sourceChildren, currentSearchIndex, el => el.Name == targetChild.Name);
            if (findIndex == -1)
                return false; // not found in source, therefore not a subset.

            if (!isSubset(sourceChildren[findIndex], targetChild))
                return false; // if the child is not a subset, then parent isn't too.

            currentSearchIndex = findIndex; // increment our search index so we won't match nodes that already passed.
        }
    }