使用LINQ在XDocument中聚合多个嵌套元素

时间:2016-02-03 15:26:54

标签: c# linq xml-parsing linq-to-xml

我有以下XML(解析为XDocument):

XDocument nvdXML = XDocument.Parse(@"<entry id='CVE-2016-1926'>
<vulnerable-configuration id='http://www.nist.gov/'>
  <logical-test operator='OR' negate='false'>
    <fact-ref name='A'/>
    <fact-ref name='B'/>
    <fact-ref name='C'/>
  </logical-test>
</vulnerable-configuration>
<vulnerable-configuration id='http://www.nist.gov/'>
  <logical-test operator='OR' negate='false'>
    <fact-ref name='X'/>
    <fact-ref name='Y'/>
    <fact-ref name='Z'/>
  </logical-test>
</vulnerable-configuration></entry>");

我想获得每个&#34;名称&#34;的单个集合/列表每个条目的属性(在这种情况下,只有一个条目,其名称列表将包含[&#39; A&#39;,&#39; B&#39;,&#39; C&#39;,&# 39; X&#39;&#39; Y&#39;&#39; Z&#39;])

这是我的代码:

var entries = from entryNodes in nvdXML.Descendants("entry")
                          select new CVE
                          {
                              //VulnerableConfigurations = (from vulnCfgs in entryNodes.Descendants(vulnNS + "vulnerable-configuration").Descendants(cpeNS + "logical-test")
                              //                            select new VulnerableConfiguration
                              //                            {
                              //                                Name = vulnCfgs.Element(cpeNS + "fact-ref").Attribute("name").Value
                              //                            }).ToList()
                              VulnerableConfigurations = (from vulnCfgs in entryNodes.Descendants("vulnerable-configuration")
                                                          from logicalTest in vulnCfgs.Descendants("logical-test")
                                                          select new VulnerableConfiguration
                                                          {
                                                              Name = logicalTest.Element("fact-ref").Attribute("name").Value
                                                          }).ToList()
                          };

不幸的是,此(已注释和未注释)查询仅导致漏洞配置 [&#39; A&#39;&#39; X&#39;] ,而不是 [ &#39; A&#39;&#39; B&#39;,&#39; C&#39;&#39; X&#39;&#39; Y&#39;&#39; Z& #39]

如何修改我的查询,以便选择每个列表的每个元素(假设可能有1个以上的嵌套列表)?

注意,我确实搜索过dup,虽然有类似的问题,但大多数都非常具体,要求分组/求和/操作,或者与XML解析无关。

最终工作代码(感谢接受的答案):

var entries = from entryNodes in nvdXML.Descendants("entry")
                          select new CVE
                          {
                              VulnerableConfigurations = (from vulnCfgs in entryNodes.Descendants("fact-ref")
                                                          select new VulnerableConfiguration
                                                          {
                                                              Name = vulnCfgs.Attribute("name").Value
                                                          }).ToList()
                          };

1 个答案:

答案 0 :(得分:1)

如果您只有一个条目,可以试试这个:

var entries =(from fact in nvdXML.Descendants("fact-ref")
              select new VulnerableConfiguration
                         {
                           Name = fact.Attribute("name").Value
                         }).ToList();

Descendants方法将按文档顺序返回与该名称匹配的所有后代元素。

如果您有多个条目,并且想要为每个条目返回一个列表,则可以执行以下操作:

var entries =(from entry in nvdXML.Descendants("entry")
              select  entry.Descendants("fact-ref").Select(f=>f.Attribute("name").Value).ToList()
             ).ToList();

在这种情况下,您将获得一个列表列表(List<List<string>>

更新

您的问题是因为您在logical-test元素上讨论您的查询,而在您的xml中,您有两个元素。现在,在select您使用的Element方法中,您只使用了一个元素,结果就是AX fact-ref元素中的第一个logical-test元素