如何从XML获取指定平台的SymbolRoot,替换硬编码生成商品符号
解决从XML动态获取商品符号根代码的问题
问题背景
我们需要从XML文件生成商品符号,目前已经能正确获取合约月份信息,但商品符号的根部分(对应XML里的<SymbolRoot>下的<Platform>)还是硬编码的"C ",需要根据传入的platform参数,动态匹配对应<Platform>元素的value属性值来替换这个硬编码值。
原始XML结构
<Commodities> <Grains> <Commodity title="Corn" value="0" name="corn"> <Specs> <!-- other elements --> <SymbolRoot> <Platform value="ZC" name="globex"/> <Platform value="C " name="bloomberg"/> </SymbolRoot> </Specs> <ContractMonths firstnoticedaterule="" lasttradedaterule="The business day prior to the 15th calendar day of the contract month"> <Month value="Mar"> <Year value="2018" firstnoticedate="02/28/18" lasttradedate="03/14/18" dateformat="mm/dd/yy"/> <Year value="2019" firstnoticedate="02/28/19" lasttradedate="03/14/19" dateformat="mm/dd/yy"/> <Year value="2020" firstnoticedate="02/28/20" lasttradedate="03/13/20" dateformat="mm/dd/yy"/> </Month> </ContractMonths> </Commodity> </Grains> </Commodities>
现有硬编码代码
private List<string> GetAllSymbolsForContractMonths(CommodityList commodity, string platform) { var symCode = string.Empty; var yrLastDigit = DateTime.Now.Year % 10; //get the contract month symbol codes var query = _doc.Descendants("Commodity") .Where(c => c.Attribute("name")?.Value == commodity.ToString().ToLower()) .Descendants("ContractMonths").Elements("Month") .Select(v => "C " + SymbolHelpers.GetSymbolContractMonthLetter(v.Attribute("value")?.Value) + yrLastDigit + " Comdty") .ToList(); return query; }
解决方案:动态获取Platform的Value
我们需要先定位到目标商品的<SymbolRoot>节点,再根据传入的platform参数匹配对应的<Platform>元素,提取其value属性。修改后的代码如下:
private List<string> GetAllSymbolsForContractMonths(CommodityList commodity, string platform) { var yrLastDigit = DateTime.Now.Year % 10; var commodityName = commodity.ToString().ToLower(); // 1. 定位到目标商品节点 var targetCommodity = _doc.Descendants("Commodity") .FirstOrDefault(c => c.Attribute("name")?.Value == commodityName); if (targetCommodity == null) { // 处理找不到商品的情况,比如返回空列表或者抛出异常 return new List<string>(); } // 2. 在目标商品下查找匹配platform的Platform节点 var targetPlatform = targetCommodity.Descendants("SymbolRoot") .Elements("Platform") .FirstOrDefault(p => p.Attribute("name")?.Value.Equals(platform, StringComparison.OrdinalIgnoreCase) == true); // 3. 获取平台对应的符号根代码,找不到的话可以设置默认值或者抛出异常 var symCode = targetPlatform?.Attribute("value")?.Value ?? "C "; // 保留原硬编码作为默认值 // 4. 生成商品符号列表 var query = targetCommodity.Descendants("ContractMonths") .Elements("Month") .Select(v => $"{symCode}{SymbolHelpers.GetSymbolContractMonthLetter(v.Attribute("value")?.Value)}{yrLastDigit} Comdty") .ToList(); return query; }
关键说明
- 精准定位节点:先找到目标商品节点,再在其内部查找
<SymbolRoot>,避免匹配到其他商品的平台信息 - 平台匹配逻辑:用
StringComparison.OrdinalIgnoreCase做不区分大小写的匹配(如果你的XML里name属性是大小写敏感的,可以去掉这个参数) - 空值处理:用空合并运算符
??设置默认值,避免找不到平台节点时出现空引用错误,你也可以根据业务需求改成抛出异常 - 代码可读性:拆分了查询逻辑,每一步都有明确的目标,更容易维护
内容的提问来源于stack exchange,提问作者dinotom
相关产品推荐
相关产品推荐

