简体   繁体   中英

linq to xml skipwhile() takewhile()

I have this xml

<root>
<TR_ZAL IDZ="cOY9" O="0">
</TR_ZAL>
<TR_ZAL IDZ="FOXd" O="10">
</TR_ZAL>
<TR_ZAL IDZ="wAW5" O="1">
<TR_ZAL IDZ="AWak" O="1">
</TR_ZAL>
<TR_ZAL IDZ="XpPp" O="10">
</TR_ZAL>
<TR_ZAL IDZ="asTu" O="10">
</TR_ZAL>
<TR_ZAL IDZ="y9VV" O="1">
</TR_ZAL>
</root>

and I know the IDZ "AWak" and my task is to get the element with known IDZ and all after it until the next element with same attribute O and if there isn't any other then I should get all remaining elements. In this case it should be

<TR_ZAL IDZ="AWak" O="1">
</TR_ZAL>
<TR_ZAL IDZ="XpPp" O="10">
</TR_ZAL>
<TR_ZAL IDZ="asTu" O="10">
</TR_ZAL>

so i tried to use linq, but I can't find my mistake, so can anyone please halp me?

IEnumerable<XElement> rozsah = xmlText.Root.Elements("TR_ZAL")
                  .SkipWhile(x => x.Attribute("IDZ").Value != "AWak")
                  .Take(1)
                  .TakeWhile(x =>Convert.ToInt32(x.Attribute("O").Value) != o);

I guess that your XML should be valid with this change:

<root>
<TR_ZAL IDZ="cOY9" O="0">
</TR_ZAL>
<TR_ZAL IDZ="FOXd" O="10">
</TR_ZAL>
<TR_ZAL IDZ="wAW5" O="1">
</TR_ZAL>
<TR_ZAL IDZ="AWak" O="1">
</TR_ZAL>
<TR_ZAL IDZ="XpPp" O="10">
</TR_ZAL>
<TR_ZAL IDZ="asTu" O="10">
</TR_ZAL>
<TR_ZAL IDZ="y9VV" O="1">
</TR_ZAL>
</root>

If this is true, then answer on your question below:

int? o = null;
IEnumerable<XElement> rozsah = xmlText.Root
    // Getting all child 'TR_ZAL' from root object
    .Elements("TR_ZAL")
    // Ignoring until we will not meet TR_ZAL with IDZ == AWak
    .SkipWhile(x => x.Attribute("IDZ").Value != "AWak")
    // Cache the first value of elements in collection and compare each next item
    // we want to take only items which does not have the same value
    .TakeWhile(x =>
        {
            int oAttributeValue = XmlConvert.ToInt32(x.Attribute("O").Value);

            if (!o.HasValue)
            {
                o = oAttributeValue;
                return true;
            }
            else
            {
                return o != oAttributeValue;
            }
        });

You linq has a bug that when you find first IDZ = AWak - next your step is to take 1 element Take(1) and so after this Take(1) will return you collection with just one element, so next your step TakeWhile(...) operates on the collection with this one element, not with the rest of elements after.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM