Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check if XElement is null globally

I have a class what takes care of reading and holding the XML file. Right now a simple version of it looks like this:

public class EstEIDPersoConfig
{
    public bool LaunchDebugger { get ; set; }
    public string Password { get; set; }
    public int Slot { get; set; }
    public string Reader { get; set; }
    public string TestInput { get; set; }
    public bool Logging { get; set; }

    public EstEIDPersoConfig()
    {
        XElement xml = XElement.Load(myxml.xml);
        XElement Configuration = xml.Element("Configuration");

        LaunchDebugger = Convert.ToBoolean(Configuration.Element("LaunchDebugger").Value);
        Password = Configuration.Element("Password").Value;
        Slot = Convert.ToInt32(Configuration.Element("Slot").Value);
        Reader = Configuration.Element("Reader").Value;
        TestInput = Configuration.Element("TestInput").Value;
        Logging = Convert.ToBoolean(Configuration.Element("Logging").Value);
     }
 }

And there will be more later. so the problem is that if some element does not exist in xml i get System.NullReferenceException. So i need to check if the element is null or not. Heres one way to do this:

var value = Configuration.Element("LaunchDebugger").Value;
if (value != null)
    LaunchDebugger = Convert.ToBoolean(value);
else
    throw new Exception("LaunchDebugger element missing from xml!");

But doing that for every element would be just too much. So i need some good ideas how to simplify this system so it wouldn't end up in 1000 lines of code.

EDIT: Edited the last code snippet, the idea was not to set a default value, idea was to notify the user that this element whats null is missing from the xml.

like image 392
hs2d Avatar asked Oct 26 '11 07:10

hs2d


5 Answers

The idea here comes directly from abatischev's answer so he deserves the credit.

As perscribed by Microsoft here you can just cast the XElement to the type you desire.

LaunchDebugger = (bool?)Configuration.Element("LaunchDebugger");

if you want to handle the null case I guess you could do

LaunchDebugger = (bool)(Configuration.Element("LaunchDebugger") ?? true);

or perhaps

LaunchDebugger = (bool)(Configuration.Element("LaunchDebugger") ?? false);

depending on your business logic. If you do the same coalescene for a specific type it may be appropriate to wrap this one liner in a method, extension or otherwise but I'm uncertain it would add much.

like image 117
Jodrell Avatar answered Oct 20 '22 01:10

Jodrell


(bool)Configuration.Element("LaunchDebugger")

or

(bool?)Configuration.Element("LaunchDebugger")

should not throw exception.

See MSDN:

  • XElement Explicit Conversion (XElement to Boolean)
  • XElement Explicit Conversion (XElement to Nullable<Boolean>)
like image 37
abatishchev Avatar answered Oct 20 '22 03:10

abatishchev


I have an extension method that I use for just this kind of thing:

    public static T GetValue<T>(
            this XElement @this,
            XName name, 
            Func<XElement, T> cast, 
            Func<T> @default)
    {
        var e = @this.Element(name);
        return (e != null) ? cast(e) : @default();
    }

It gives you the casting required and also a default value factory.

Here's how you'd use it:

LaunchDebugger = Configuration.GetValue("LaunchDebugger",
    x => Convert.ToBoolean(x), () => false);
Password = Configuration.GetValue("CMKPassword", x => (string)x, () => "");
Slot = Configuration.GetValue("CMKSlot", x => (int)x, () => -1);
Reader = Configuration.GetValue("Reader", x => (string)x, () => "");
TestInput = Configuration.GetValue("TestInput", x => (string)x, () => "");
Logging = Configuration.GetValue("Logging",
    x => Convert.ToBoolean(x), () => false);
like image 22
Enigmativity Avatar answered Oct 20 '22 01:10

Enigmativity


Extract the logic to a method and have overloaded methods for Int32,boolean and other data types conversion.

public static void GetElementValue(XElement xElement, string parameter, out bool value)
    {
        var stringValue = xElement.Element(parameter).Value;
        value = false;
        if (value != null)
            value = Convert.ToBoolean(stringValue);
    }
like image 2
luqi Avatar answered Oct 20 '22 02:10

luqi


You can define a method to extract the value for you and do some checking on null there. So wrap the value retrieval in your own method like so:

public string GetXMLValue(XElement config, string elementName){
    var element = Configuration.Element(elementName);

    if(element == null)
        return String.Empty;

    return element.Value;
}

Of course you can extend this to work correctly with parsing to boolean etc.

like image 1
Bas Slagter Avatar answered Oct 20 '22 03:10

Bas Slagter