Tutorial :How to check for existence of an element with XElement?



Question:

Notice in this code I am trying to check for the existence of the rdfs:range element before trying to select it. I do this to avoid a possible null reference exception at runtime.

    private readonly XNamespace rdf = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";      private readonly XNamespace rdfs = "http://www.w3.org/2000/01/rdf-schema#";      private readonly XElement ontology;        public List<MetaProperty> MetaProperties      {          get          {              return (from p in ontology.Elements(rdf + "Property")                      select new MetaProperty                      {                          About = p.Attribute(rdf + "about").Value,                          Name = p.Element(rdfs + "label").Value,                          Comment = p.Element(rdfs + "comment").Value,                          RangeUri = p.Elements(rdfs + "range").Count() == 1 ?                              p.Element(rdfs + "range").Attribute(rdf + "resource").Value :                              null                      }).ToList();          }      }  

This is kinda bugging me, what I really want to do is something like this:

p.HasElements(rdfs + "range") ?      p.Element(rdfs + "range").Attribute(rdf + "resource").Value :      null  

However there is no HasElement(string elementName) method available.

I guess I could create a method extension to do this, but am wondering if there is something already built in or if there are other ways to do this?


Solution:1

Same basic thing, but neater

return (from p in ontology.Elements(rdf + "Property")   let xRange = p.Element(rdfs + "range")   select new MetaProperty   {       About = p.Attribute(rdf + "about").Value,       Name = p.Element(rdfs + "label").Value,       Comment = p.Element(rdfs + "comment").Value,       RangeUri = xRange == null ? null : xRange.Attribute(rdf + "resource").Value   }).ToList();   


Solution:2

You can use:

p.Elements(rdfs + "range").SingleOrDefault()  

which will return null if there are no elements. It will throw an exception if there's more than one matching element - FirstOrDefault() will avoid this if it's not the desired behaviour.

EDIT: As per my comment, and taking advantage of the conversion from XAttribute to string also handling nulls:

return (from p in ontology.Elements(rdf + "Property")           select new MetaProperty                      {                          About = p.Attribute(rdf + "about").Value,                          Name = p.Element(rdfs + "label").Value,                          Comment = p.Element(rdfs + "comment").Value,                          RangeUri = (string) p.Elements(rdf + "range")                                              .Attributes(rdf + "resource")                                              .FirstOrDefault()                      }).ToList();   

If you have the same thing in many places, you could write an extension method to encapsulate that very easily:

public static XAttribute FindAttribute(this XElement element,      XName subElement, XName attribute)  {      return element.Elements(subElement).Attributes(attribute).FirstOrDefault();  }  

So the RangeUri bit would be:

RangeUri = (string) p.FindAttribute(rdf + "range", rdf + "resource")  

Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »