2010-07-28 43 views
3

注意在此代碼中,我試圖在選擇它之前檢查rdfs:range元素的存在。我這樣做是爲了在運行時避免可能的空引用異常。如何使用XElement檢查元素的存在性?

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(); 
     } 
    } 

這有點兒煩我,我真正想要做的是這樣的:

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

但是沒有HasElement(string elementName)方法可用。

我想我可以創建一個方法擴展來做到這一點,但我想知道是否有內置的東西,或者如果有其他方法可以做到這一點?

回答

1

相同的基本的東西,但整潔的

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(); 
+0

是的,這個更簡潔。我喜歡它,我想我會用它來檢查一些其他屬性。 – 2010-07-28 10:35:16

7

您可以使用:

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

將返回null如果沒有的元素。如果有多個匹配元素,它會拋出一個異常 - 如果它不是所需的行爲,則FirstOrDefault()將避免這種情況。

編輯:按我的意見,並考慮轉換的優勢,從XAttribute串也處理空值:

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(); 

如果你在很多地方同樣的事情,你可以寫一個擴展方法來封裝這很容易:

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

所以RangeUri位將是:

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

很高興知道,我忘了FirstOrDefault功能。我看到的唯一潛在問題是,我不能僅僅調用.Attribute就可以了,因爲我不知道它是否會返回null。 – 2010-07-28 10:40:14

+1

@保羅:確實。你可能想編寫自己的擴展方法'AttributeOrNull',它適當地接受空值。或者,你可以使用'Elements(rdfs +「range」)。屬性(rdf +「resource」)。FirstOrDefault()' – 2010-07-28 10:54:46