簡體   English   中英

如何使此LINQ to XML查詢更優雅?

[英]How to make this LINQ to XML query more elegant?

我收集了如下的MODS記錄:

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

我認為可以更好地編寫此查詢。 怎么樣?

我知道您只想使用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>(); 

我將使用擴展方法語法,並使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;
    }

這只會進行名稱匹配。 但是您可以將這些方法用作構建塊。 無論您在哪里查詢此類文檔,都可以重用匹配的名稱部分,因此不可重用的部分很小。 查詢的后半部分可以從此示例派生。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM