Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check for existence of an element with XElement?

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?

like image 394
Paul Fryer Avatar asked Feb 04 '26 04:02

Paul Fryer


1 Answers

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")
like image 188
Jon Skeet Avatar answered Feb 05 '26 18:02

Jon Skeet