如何将XmlNodeList拆分为两个子XmlNodeList?

时间:2018-05-08 21:53:14

标签: c# xmlnodelist

如何将XmlNodeList拆分为两个较小的XmlNodeList,其中一个大小为N,另一个大小为N?

请参阅下面的示例以及我尝试使用此处的位置:

    public static void Main(string[] args)
    {
        XmlDocument someDoc = new XmlDocument();
        someDoc.LoadXml(@"<bananas>
                            <banana tasty='yes'></banana>
                            <banana tasty='very'></banana>
                            <banana tasty='amazing'></banana>
                            <banana tasty='mind-blowing'></banana>
                            <banana tasty='disgusting'></banana>
                          </bananas>");
        XmlNodeList bananaNodeList = someDoc.SelectNodes("//banana");
        eatSomeBananas(bananaNodeList, 2);
    }

    /** Splits a XmlNodeList into two XmlNodeList, first one is a slice from 0 to numberOfBananas-1, and the other slice is from numberOfBananas and onwards
    */
    public static void eatSomeBananas(XmlNodeList subBananaNodeList, int numberOfBananas)
    {
        XmlNodeList bananasToEat = subBananaNodeList.Cast<XmlNode>().Take(numberOfBananas) as XmlNodeList; //Error down-casting - null!
        if (bananasToEat == null)
            Console.WriteLine("Error! Did not work");
        /*else 
            doSomethingHere(bananasToEat); */
        XmlNodeList remainingBananas = subBananaNodeList.Cast<XmlNode>().Skip(numberOfBananas) as XmlNodeList; //Error down-casting - null!
        eatSomeBananas(remainingBananas, numberOfBananas);
    }

我试图将XmlNodeList投射到IEnumerable<XmlNode>(因为前者继承了后者) - 我相信这应该是一个向上的。我不能在之后将其转回XmlNodeList吗?但如果没有,为什么不呢?

2 个答案:

答案 0 :(得分:2)

  

之后我不能把它转发回XmlNodeList吗?但如果没有,为什么不呢?

不,因为Skip返回的值不是XmlNodeList。它只被声明为IEnumerable<XmlNode>,并且我希望Skip实现可能使用迭代器块...当然,如果{{{I}我会感到惊讶1}}有Skip的详细知识。 XmlNodeList将以完全相同的方式工作。

就个人而言,我完全避免使用旧的XML API,只使用LINQ to XML。这自然与LINQ一起发挥 - 并且通常是一个更好的XML API,IMO。

你没有 使用它,请注意 - 您只需更改整个代码即可使用Take代替IEnumerable<XmlNode>

XmlNodeList

然后,当您调用方法时,您只需拨打public static void eatSomeBananas(IEnumerable<XmlNode> subBananaNodeList, int numberOfBananas) { IEnumerable<XmlNode> bananasToEat = subBananaNodeList.Take(numberOfBananas); IEnumerable<XmlNode> remainingBananas = subBananaNodeList.Skip(numberOfBananas); // Added condition to avoid infinite recursion if (remainingBananas.Any()) { eatSomeBananas(remainingBananas, numberOfBananas); } } 一次:

Cast

这里是LINQ to XML版本,我更喜欢:

eatSomeBananas(bananaNodeList.Cast<XmlNode>(), 2);

请注意,对于生产实现,我会避免递归并且可能会定期实现结果 - 否则它每次都会从头开始迭代,跳过负载然后再进行一些。

答案 1 :(得分:1)

我刚刚转换为IQueryable并使用它,比XmlNodeList更容易使用。

    public static void Main(string[] args)
    {
        XmlDocument someDoc = new XmlDocument();
        someDoc.LoadXml(@"<bananas>
                        <banana tasty='yes'></banana>
                        <banana tasty='very'></banana>
                        <banana tasty='amazing'></banana>
                        <banana tasty='mind-blowing'></banana>
                        <banana tasty='disgusting'></banana>
                      </bananas>");
        XmlNodeList bananaNodeList = someDoc.SelectNodes("//banana");

        var allBananas = bananaNodeList.Cast<XmlNode>().AsQueryable();

        eatSomeBananas(allBananas, 2);
    }

    public static void eatSomeBananas(IQueryable<XmlNode> subBananas, int numberOfBananas)
    {
        var bananasToEat = subBananas.Take(numberOfBananas);
        var remainingBananas = subBananas.Skip(numberOfBananas);

        Console.WriteLine(string.Format("Bananas to eat: {0}", bananasToEat.Count()));
        Console.WriteLine(string.Format("Remaining bananas: {0}", remainingBananas.Count()));
        if (!bananasToEat.Any())
            Console.WriteLine("Error! Did not work (not enough bananas!)");
        else 
            eatSomeBananas(remainingBananas, numberOfBananas);
    }

输出:

Bananas to eat: 2
Remaining bananas: 3
Bananas to eat: 2
Remaining bananas: 1
Bananas to eat: 1
Remaining bananas: 0
Bananas to eat: 0
Remaining bananas: 0
Error! Did not work (not enough bananas!)