我有两个使用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;
答案 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.
}
}