我有一组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查询搜索colloction以查找与某个具有某个角色的人关联的记录,如下所示:
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 :(得分: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>();
答案 1 :(得分:2)
我会使用Extension方法语法,并使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;
}
这只是名称匹配。但是您可以将这些方法用作构建块。您可以在查询此类文档的任何位置重复使用名称部分匹配,因此不可重用的部分很小。查询的后半部分可以从此示例派生。