Home > Blockchain >  Using XDocument.Descendants with a coalesce operator ?? and nullable types
Using XDocument.Descendants with a coalesce operator ?? and nullable types

Time:11-09

Compiler: Visual Studio 2019
Framework: .Net 2.1

Given a XML file like this:

<root>
  <data>
        <AdditionalOrderInfo>
            <AdditionalInfoItem key="{4567B566-A0A2-4214-B7E7-814FE179CDFC}" value="ScanItDental"/>
            <AdditionalInfoItem key="GlobalOrderID" value="EDC531BE6A0D4DC5BFEA0C6081D9F26B"/>
            <AdditionalInfoItem key="CreatedIn" value="2.20.1.2"/>
        </AdditionalOrderInfo>  
    </data>
</root>

I need to get AdditionalInfoItem only for certain key values.

To avoid null errors I'm trying to use nullable types and coalesce operator ??

var additionalOrderInfo = document.Descendants(ns   "AdditionalOrderInfo").First();
var value = additionalOrderInfo.Descendants(ns   "AdditionalInfoItem")?.Where(el => el.Attribute("key").Value == "SomeKey")?.First()?.Attribute("value")?.Value ?? "";

But if key doesn't exists it returns:

Sequence contains no elements.

I've ended using a foreach loop in this way:

var additionalOrderInfo = document.Descendants(ns   "AdditionalOrderInfo").First();
foreach (var item in additionalOrderInfo.Descendants(ns   "AdditionalInfoItem"))
{
    switch (item.Attribute("key").Value)
    {
        case "SomeKey1":
            Order.SomeKey1 = item.Attribute("value").Value;
            break;
        case "SomeKey2":
            Order.SomeKey2 = item.Attribute("value").Value;
            break;
    }
}

Is there a way to avoid the foreach loop and read the value using a single line of code?

CodePudding user response:

Try use FirstOrDefault instead of First only after Where selector:

var value = additionalOrderInfo.Descendants(ns   "AdditionalInfoItem")?
                               .Where(el => el.Attribute("key").Value == "SomeKey")?
                               .FirstOrDefault()? // <--- Here
                               .Attribute("value")?.Value ?? "";

If Where(el => el?.Attribute("key")?.Value == "SomeKey") return 0 elements, you getting Sequence contains no elements exception, so you can't get First element of it. FirstOrDefault returns null instead, so next nullcheck ? goes forward.

  • Related