2010-03-01 24 views
2

我的MODS記錄的集合,看起來像這樣:如何讓這個LINQ to XML查詢更優雅?

<modsCollection> 
<mods [namespaces etc] > 
    <genre authority="diva" type="contentType" lang="eng">Other academic</genre> 
    <genre authority="diva" type="contentType" lang="swe">Övrigt vetenskapligt</genre> 
    <name type="personal"> 
     <namePart type="family">Svensson</namePart> 
     <namePart type="given">Sven</namePart> 
     <namePart type="date">1880-</namePart> 
     <role> 
     <roleTerm type="code" authority="marcrelator">aut</roleTerm> 
     </role> 
     <affiliation>Stockholms universitet, institutionen institutionen</affiliation> 
    </name> 
[...] 
</mods> 
<mods/> 
<mods/> 
</modsCollection> 

我的LINQ查詢來搜索一個特定的人有一定的作用附屬記錄大全看起來是這樣的:

XElement[] hits = (from record in x.Root.Elements(modsV3 + "mods").Elements(modsV3 + "name") 
    from r1 in record.Elements(modsV3+"namePart") 
    where 
     r1.HasAttributes && 
     r1.Attribute("type").Value == "family" && 
     r1.Value == familyName 
    from r2 in record.Elements(modsV3 + "namePart") 
    where 
     r2.HasAttributes && 
     r2.Attribute("type").Value == "given" && 
     r2.Value == givenName 
    from r3 in record.Elements(modsV3 + "role").Elements(modsV3+"roleTerm") 
    where 
     r3.HasAttributes && 
     r3.Attribute("type").Value == "code" && 
     r3.Value == "aut" 
    select r1.Parent.Parent).ToArray<XElement>();  

我認爲這個查詢可以寫得更好。怎麼樣?

+0

只是爲了clearyfy: 我正在尋找一個LINQ查詢,不同的條件,把在多個decendant節點一個很好的例子。 – Fontanka16 2010-03-01 13:29:22

回答

2

我知道你希望只使用LINQ,但也許使用XPath混合簡化代碼:

XElement[] hits = (from record in config.Elements(modsV3 + "mods").Elements(modsV3 + "name") 
where record.XPathSelectElement(string.Format("./{0}namePart[@type='family' and .='{1}']", modsV3, familyName)) != null && 
     record.XPathSelectElement(string.Format("./{0}namePart[@type='given' and .='{1}']", modsV3, givenName)) != null && 
     record.XPathSelectElement(string.Format("./{0}role/{0}roleTerm[@type='code' and .='aut']", modsV3)) != null 
select record.Parent).ToArray<XElement>(); 
2

我會使用擴展方法的語法,使LINQ的過濾方法,象下面這樣:

private static XElement[] GetHits(XDocument x, string modsV3, string givenName, string familyName) 
    { 

     return x.Root.Elements(modsV3 + "mods") 
      .MatchNamePart("given", givenName) 
      .MatchNamePart("family", familyName).ToArray(); 
    } 

    private static string modsV3 = "whatever"; 

    private static IEnumerable<XElement> MatchNamePart(this IEnumerable<XElement> records, string type, string givenName) 
    { 
     return records.Where(rec => rec.Element(modsV3 + "name"). 
      Elements(modsV3 + "namePart").Any(r1 => HasAttrib(r1, type, givenName))); 
    } 

    private static bool HasAttrib(XElement element, string attribName, string value) 
    { 
     return element.HasAttributes && 
       element.Attribute("type").Value == attribName && 
       element.Value == value; 
    } 

這不僅會名稱匹配。但是您可以將這些方法用作構建塊。您可以重複使用的名稱部分匹配的地方查詢該類型的文件,所以不能重複使用的部分小。查詢的後半部分可以從這個例子中派生出來。