选择具有不同层次结构的XML节点以比较值的更好方法是什么?

时间:2018-09-18 00:05:18

标签: c# .net xml

我正在用下面的代码比较两个XML节点:

List<string> lolwa = new List<string>();
List<string> lolwaforever = new List<string>();
XmlNodeList subList = subListRoot.SelectSingleNode("Mainnode").SelectNodes("Subnodes");
XmlNodeList masterList = masterListRoot.SelectSingleNode("Mainnode").SelectNodes("Subnodes");
foreach (XmlNode item in subList)
    {
        lolwa.Add(item.OuterXml + item.InnerXml + item.InnerText);
    }
foreach (XmlNode item in masterList)
    {
        lolwaforever.Add(item.OuterXml + item.InnerXml + item.InnerText);
    }
match = !lolwa.Except(lolwaforever).Any(); //check if lolwa is a subset of lolwaforever

我需要对多个节点执行此过程,因此我将有多个masterList,subList和每个列表的foreach循环。另外,如您所见,“主节点”和“子节点”是硬编码的或将是常量。

有没有更漂亮/更好的方法来实现这一目标?

1 个答案:

答案 0 :(得分:1)

这里是如何实现它的示例。我建议分开使用IsSubsetOf方法来处理XmlNodeList个项目,并使用另一个重载来处理List<XmlNodeList>实例。另外,我还随意添加了XNodeEqualityComparer用于节点比较而不是收集字符串。请注意,比较器与名称空间System.Xml.Linq中的类一起使用。

[Test]
public void CompareXmlNodeLists()
{
    // Arrange
    XmlDocument masterListRoot = new XmlDocument();
    masterListRoot.LoadXml(@"<?xml version=""1.0"" encoding=""UTF-8""?>
                            <Mainnode>
                                <Subnodes id=""1"">
                                <SubChild>Child1</SubChild>
                                </Subnodes>
                                <Subnodes id=""2"">
                                <SubChild>Child2</SubChild>
                                </Subnodes>
                                <Subnodes id=""3"">
                                <SubChild>Child3</SubChild>
                                </Subnodes>
                            </Mainnode>");


    XmlDocument subListRoot = new XmlDocument();
    subListRoot.LoadXml(@"<?xml version=""1.0"" encoding=""UTF-8""?>
                            <Mainnode>
                                <Subnodes id=""1"">
                                <SubChild>Child1</SubChild>
                                </Subnodes>
                                <Subnodes id=""2"">
                                <SubChild>Child2</SubChild>
                                </Subnodes>
                            </Mainnode>");

    XmlNodeList subList = subListRoot.SelectSingleNode("Mainnode").SelectNodes("Subnodes");
    XmlNodeList masterList = masterListRoot.SelectSingleNode("Mainnode").SelectNodes("Subnodes");

    // Act
    var match = IsSubsetOf(masterList, subList);
    var multipleMactch = IsSubsetOf(new List<XmlNodeList> { masterList }, new List<XmlNodeList> { subList });

    //Assert
    Assert.True(match);
    Assert.True(multipleMactch);

}

public bool IsSubsetOf(List<XmlNodeList> masters, List<XmlNodeList> subs)
{
    foreach (var sub in subs)
    {
        if (!masters.Any(x => IsSubsetOf(x, sub)))
        {
            return false;
        }
    }

    return true;
}

public bool IsSubsetOf(XmlNodeList master, XmlNodeList sub)
{
    XNodeEqualityComparer comparer = new XNodeEqualityComparer();
    var xSub = sub.Cast<XmlNode>().Select(x => XDocument.Parse(x.OuterXml));
    var xMaster = master.Cast<XmlNode>().Select(x => XDocument.Parse(x.OuterXml)).ToList();

    foreach (var subItem in xSub)
    {
        if (!xMaster.Any(x => comparer.Equals(x, subItem)))
        {
            return false;
        }
    }

    return true;
}

希望有帮助。