使用 LINQ 聚合 XDocument 中的多个嵌套元素
Using LINQ to aggregate multiple nested elements in XDocument
我有以下 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>");
我想为每个条目获取每个 "name" 属性的单个 collection/list(在这种情况下,只有一个条目,其名称列表将包含 ['A', 'B','C','X','Y','Z'])
这是我的代码:
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()
};
不幸的是,这个(注释和未注释的)查询只会导致 VulnerableConfigurations ['A','X'],而不是 ['A','B','C','X','Y','Z']
如何修改我的查询以便选择每个列表的每个元素(假设可能有 1 个以上的嵌套列表)?
注意,我确实搜索过dup的,虽然也有类似的问题,但大部分都很具体,求grouping/summing/manipulation,或者与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()
};
如果你只有一个条目,你可以试试这个:
var entries =(from fact in nvdXML.Descendants("fact-ref")
select new VulnerableConfiguration
{
Name = fact.Attribute("name").Value
}).ToList();
Descendants 方法将 return 所有与文档顺序中的名称匹配的后代元素。
如果您有多个条目并且您想要 return 每个条目的列表,您可以执行以下操作:
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
方法,它只给你一个元素,结果就是 A
和 X
,这是第一个 fact-ref
元素内 logical-test
元素
我有以下 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>");
我想为每个条目获取每个 "name" 属性的单个 collection/list(在这种情况下,只有一个条目,其名称列表将包含 ['A', 'B','C','X','Y','Z'])
这是我的代码:
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()
};
不幸的是,这个(注释和未注释的)查询只会导致 VulnerableConfigurations ['A','X'],而不是 ['A','B','C','X','Y','Z']
如何修改我的查询以便选择每个列表的每个元素(假设可能有 1 个以上的嵌套列表)?
注意,我确实搜索过dup的,虽然也有类似的问题,但大部分都很具体,求grouping/summing/manipulation,或者与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()
};
如果你只有一个条目,你可以试试这个:
var entries =(from fact in nvdXML.Descendants("fact-ref")
select new VulnerableConfiguration
{
Name = fact.Attribute("name").Value
}).ToList();
Descendants 方法将 return 所有与文档顺序中的名称匹配的后代元素。
如果您有多个条目并且您想要 return 每个条目的列表,您可以执行以下操作:
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
方法,它只给你一个元素,结果就是 A
和 X
,这是第一个 fact-ref
元素内 logical-test
元素