给定具有以下结构的xml
<Commodity name="coffee" title="Coffee" value="7">
<Specs>
..elements removed
</Specs>
<ContractMonths lasttradedaterule="Eight business days prior to the last business day of the delivery month"
firstnoticedaterule="Seven business days prior to first business day of delivery month">
..elements removed
</ContractMonths>
<Options tf="true">
<OptionMonths delimeter="comma"
expirationdaterule="Second Friday of the calendar month preceding such regular or serial
option month; provided, however, that for each option, there will be a minimum of four
trading days between the last trading day of the expiring option and the first notice
day of the expiring future">
<Year value="2015">
..elements removed
</Year>
<Year value="2016">
..elements removed
</Year>
<Year value="2017">
..elements removed
</Year>
<Year value="2018">
<Jan expiration="" associatedcontract="Mar" />
<Feb expiration="" associatedcontract="Mar" />
<Mar expiration="02/12/18" associatedcontract="Mar" />
<Apr expiration="" associatedcontract="May" />
<May expiration="04/08/18" associatedcontract="May" />
<Jun expiration="05/11/18" associatedcontract="Jul" />
<Jul expiration="06/08/18" associatedcontract="Jul" />
<Aug expiration="07/13/18" associatedcontract="Sep" />
<Sep expiration="08/10/18" associatedcontract="Sep" />
<Oct expiration="" associatedcontract="Dec" />
<Nov expiration="" associatedcontract="Dec" />
<Dec expiration="11/09/18" associatedcontract="Dec" />
</Year>
<Year value="2019">
..elements removed
</Year>
</OptionMonths>
有超过25种商品元素
我可以使用名称属性值
来检索我想要的商品元素 var doc = XDocument.Load(@"https://batlgroupimages.blob.core.windows.net/accessibleimages/CommodityData.xml");
IEnumerable<XElement> elem =
doc.Descendants("Commodity").Where(el =>
{
var xAttribute = el.Attribute("name");
return xAttribute != null && xAttribute.Value == commodity;
});
我需要进一步向下钻取以获取年元素的节点列表,因为Year元素的value属性等于我传入的任何年份。
我试图在一个声明中做到这一点
var dates = elem.Descendants("Options/@tf='true'/OptionMonths/Year/@value='2015'");
它正确读取(对我来说)获取选项具有tf值为true的后代,获取OptionMonths / Years年份值= 2015
我可以用更短的步骤完成,但我确定有一个更快的解决方案。
更新 根据jdweng的回答,我想出了以下内容,它将返回传递给方法的年份
var year = elem.Descendants("Options")
.Where(x => x.Attribute("tf")?.Value == "true").Descendants("Year")
.Where(y => (string)y.Attribute("value") == yearvalue);
答案 0 :(得分:1)
请尝试以下操作:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = @"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
string xAttribute = "coffee";
Dictionary<int, Dictionary<string, KeyValuePair<string, string>>> dict = doc.Descendants("Commodity").Where(el => xAttribute == (string)el.Attribute("name"))
.Select(x => x.Descendants("Year")
.GroupBy(s => (int)s.Attribute("value"), t => t.Elements()
.GroupBy(u => u.Name.LocalName, v => new KeyValuePair<string, string>((string)v.Attribute("expiration"), (string)v.Attribute("associatedcontract")))
.ToDictionary(u => u.Key, v => v.FirstOrDefault()))
.ToDictionary(s => s.Key, t => t.FirstOrDefault())).FirstOrDefault();
}
}
}