-->

How can i check if this XElement is not null befor

2019-05-27 05:50发布

问题:

I'm populating an anonymous object from an XML file. Up until now,

commentary.Elements("Commentator")

has always had a value so i've never had to check for null. I've had to remove that though, and now it's failing when it tries to read that line.

I'm looking at the code and I don't know what to change though, because its being selected into a property of an anonymous object.

var genericOfflineFactsheet = new
    {
        Commentary = (from commentary in doc.Elements("Commentary")
                      select new
                      {
                          CommentaryPage = (string)commentary.Attribute("page"),
                          BusinessName = (string)commentary.Attribute("businessName"),
                          Commentator = (from commentator in commentary.Elements("Commentator")
                                         select new CommentatorPanel // ASP.NET UserControl
                                         {
                                             CommentatorName = (string)commentator.Attribute("name"),
                                             CommentatorTitle = (string)commentator.Attribute("title"),
                                             CommentatorCompany = (string)commentator.Attribute("company")
                                         }).FirstOrDefault()
                      }).FirstOrDefault()

The thing is, I can't completely remove the line because sometimes commentary.Elements("Commentator") does have a value. I'm sure this issue has been dealt with before, but I can't see what to do. Any ideas?

回答1:

Just add a null check. (code below should be a good tester. Has one with and one without Commentator)

XDocument doc = new XDocument(
    new XDeclaration("1.0", "utf-8", "yes"),
    new XComment("Example"),
new XElement("Commentarys",
        new XElement("Commentary",
            new XAttribute("page", "2"),
            new XAttribute("businessName", "name"),
            new XElement("Commentator",
               new XAttribute("name", "name"),
                new XAttribute("title", "title")
            )
         )
        ,
        new XElement("Commentary",
            new XAttribute("page", "3"),
            new XAttribute("businessName", "name2")

            )
    )
    );
var genericOfflineFactsheet = new
{
    Commentary = (
           from commentary in doc.Elements()
                .First().Elements("Commentary")
           select new
          {
              CommentaryPage = (string)commentary.Attribute("page"),
              BusinessName = (string)commentary.Attribute("businessName"),
              Commentator = (from commentator in commentary.Elements("Commentator")
                             where commentator != null //<-----you need to add this line
                             select new // ASP.NET UserControl
                             {
                                 CommentatorName = (string)commentator.Attribute("name"),
                                 CommentatorTitle = (string)commentator.Attribute("title"),
                                 CommentatorCompany = (string)commentator.Attribute("company")
                             }

                             ).FirstOrDefault()
          }
 ).FirstOrDefault()
};


回答2:

Untested...

how about something like:

  XElement xe = doc.Elements("Commentary").FirstOrDefault();
  Commentary = xe == null ? null :
    select new { ....snip....


回答3:

This is a case where I might consider the ?? (coalesce) operator.

null ?? x --> x

In this case you could get away with coalescing to an empty Enumerable.



回答4:

I use the ? operator this way to prevent a XMLElement to be generated:

  • if the object I use is not null, I return a single new XElement in an array
  • if it is null, I return a Enumerable.Empty

Example:

var xml = new XElement("Root",
    myobject == null ? Enumerable.Empty<XElement>() : <= empty IEnumerable if it is null
                       new []                         <= a array with a XElement
                           { 
                               new XElement("myobject", 
                                   new XAttribute("Name", myobject.Name),
                                   new XAttribute("Type", myobject.Type)
                               ...)
                           },
    ...);

In this case, the XElement will not be generated if the object involved in its creation is null.