基于列表从 XDocument 中检索特定元素

Retrieving specific elements from an XDocument based on a list

我有一个 xml 元素的列表存储在 class:

public class clsField
{
    public string fieldName { get; set; }
}

然后我正在加载一个 xml 文件:

XDocument doc = XDocument.Load(fileName);

最后,我只想将上面 class 中定义的字段检索到 IEnumerable 对象中。这是我目前所拥有的:

List<clsField> lstFieldsToProcess;          
IEnumerable<XElement> allthedocs = from thedoc
                 in doc.Descendants("thedocs")
                 select
                 (
                  from fields
                  in lstFieldsToProcess
                  select XElement.Parse(fields.fieldName)
                 );

但是我在上面的代码中遇到了错误。任何帮助,将不胜感激。在此先致谢。

更新#1

伪代码:

var fieldNames = new HashSet<string>(lstFieldsToProcess.Select(c => c.fieldName));
IEnumerable<XElement> elems = from level1 in doc.Elements("thedocs")
                              let level2 = level1.Descendants()
                              where fieldNames.Contains(level2.Name.LocalName)
                              select level1;

我不太确定你想做什么。您是否要过滤掉所有具有特定名称且是名为 "thedocs" 的元素的后代的元素?

假设这是您想要做的,那么您可以执行以下操作:

IEnumerable<XElement> elems = from field in lstFieldsToProcess
                              from de in doc.Elements("thedocs").Descendants(field.fieldName)
                              select de;

// Of course this is the same:
IEnumerable<XElement> elems = lstFieldsToProcess
    .SelectMany(f => doc.Elements("thedocs").Descendants(f.fieldName));

虽然我不确定 XDocument 的效率如何,所以也许最好先取出要匹配的字段名(如果性能对您很重要,请测试两者中哪个更好):

var fieldNames = new HashSet<string>(lstFieldsToProcess.Select(c => c.fieldName));
IEnumerable<XElement> elems = from d in doc.Elements("thedocs").Descendants()
                              where fieldNames.Contains(d.Name.LocalName)
                              select d;

更新 #1 我认为几乎可以在您的伪代码中拥有它。

var fieldNames = new HashSet<string>(lstFieldsToProcess.Select(c => c.fieldName));
IEnumerable<XElement> elems = from level1 in doc.Elements("thedocs")
                              from level2 in level1.Descendants()
                              where fieldNames.Contains(level2.Name.LocalName)
                              select level1;

不过,这可以多次包含相同的 "thedocs" 元素(如果它有多个具有有效字段名的后代)。为避免这种情况,只需对结果调用 Distint()。