Множественный выбор в запросе - PullRequest
0 голосов
/ 17 мая 2018

Этот запрос строит товарные символы из 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>

На данный момент я могу получить контрактные месяцы по мере необходимости, но мне также нужен корень символа для переданной платформы. Прямо сейчас он жестко задан как "C"

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;
}

Я знаю, что есть какой-то способ сделать выбор для атрибута value элемента Platform и установить это значение в переменную symCode, но я не могу сделать это правильно. Тогда я могу просто заменить жесткое кодирование переменной.

Ответы [ 2 ]

0 голосов
/ 17 мая 2018

Просто для удовольствия есть несколько интересных сайтов для преобразования вашего XML в классы C # (например, Xml2CSharp.com ). Используя этот инструмент, вы можете создать набор классов для десериализации и затем использовать LINQ to Objects.

Commodities commodities = null;
using (var stream = new StringReader(xmlString))
{
    XmlSerializer serializer = new XmlSerializer(typeof(Commodities));
    commodities = (Commodities) serializer.Deserialize(stream);
}

var commodityName = "corn";
var platformName = "bloomberg";
var year = "2018";
var commodity = commodities.Grains.Commodity.Single(c => c.Name.Equals(commodityName, StringComparison.InvariantCultureIgnoreCase));
var symbol = commodity.Specs.SymbolRoot.Platform.Single(p => p.Name.Equals(platformName, StringComparison.InvariantCultureIgnoreCase));
var months = commodity.ContractMonths.Month.Year.Where(y => y.Value.Equals(year, StringComparison.InvariantCultureIgnoreCase));

Вот классы, которые я создал с помощью инструмента. Это, конечно, намного больше кода, но мне нравится иметь конкретные классы для работы. Надеюсь, это полезно.

[XmlRoot(ElementName = "Platform")]
public class Platform
{
    [XmlAttribute(AttributeName = "value")]
    public string Value { get; set; }
    [XmlAttribute(AttributeName = "name")]
    public string Name { get; set; }
}

[XmlRoot(ElementName = "SymbolRoot")]
public class SymbolRoot
{
    [XmlElement(ElementName = "Platform")]
    public List<Platform> Platform { get; set; }
}

[XmlRoot(ElementName = "Specs")]
public class Specs
{
    [XmlElement(ElementName = "SymbolRoot")]
    public SymbolRoot SymbolRoot { get; set; }
}

[XmlRoot(ElementName = "Year")]
public class Year
{
    [XmlAttribute(AttributeName = "value")]
    public string Value { get; set; }
    [XmlAttribute(AttributeName = "firstnoticedate")]
    public string Firstnoticedate { get; set; }
    [XmlAttribute(AttributeName = "lasttradedate")]
    public string Lasttradedate { get; set; }
    [XmlAttribute(AttributeName = "dateformat")]
    public string Dateformat { get; set; }
}

[XmlRoot(ElementName = "Month")]
public class Month
{
    [XmlElement(ElementName = "Year")]
    public List<Year> Year { get; set; }
    [XmlAttribute(AttributeName = "value")]
    public string Value { get; set; }
}

[XmlRoot(ElementName = "ContractMonths")]
public class ContractMonths
{
    [XmlElement(ElementName = "Month")]
    public Month Month { get; set; }
    [XmlAttribute(AttributeName = "firstnoticedaterule")]
    public string Firstnoticedaterule { get; set; }
    [XmlAttribute(AttributeName = "lasttradedaterule")]
    public string Lasttradedaterule { get; set; }
}

[XmlRoot(ElementName = "Commodity")]
public class Commodity
{
    [XmlElement(ElementName = "Specs")]
    public Specs Specs { get; set; }
    [XmlElement(ElementName = "ContractMonths")]
    public ContractMonths ContractMonths { get; set; }
    [XmlAttribute(AttributeName = "title")]
    public string Title { get; set; }
    [XmlAttribute(AttributeName = "value")]
    public string Value { get; set; }
    [XmlAttribute(AttributeName = "name")]
    public string Name { get; set; }
}

[XmlRoot(ElementName = "Grains")]
public class Grains
{
    [XmlElement(ElementName = "Commodity")]
    public List<Commodity> Commodity { get; set; }
}

[XmlRoot(ElementName = "Commodities")]
public class Commodities
{
    [XmlElement(ElementName = "Grains")]
    public Grains Grains { get; set; }
}
0 голосов
/ 17 мая 2018

Разделите ваш запрос на две части. Сначала найдите товарный элемент.

Из этого элемента найдите символ платформы. Затем создайте список.

private List<string> GetTypeFromVariable(CommodityList commodity, string platform)
{
    var yrLastDigit = DateTime.Now.Year % 10;

    var commodityElement = _doc.Descendants("Commodity")
        .Where(x => x.Attribute("name")?.Value.Equals(commodity.ToString(), StringComparison.InvariantCultureIgnoreCase) ?? false)
        .Single();

    var symbol = commodityElement.Descendants("Platform")
        .Where(x => x.Attribute("name")?.Value.Equals(platform, StringComparison.InvariantCultureIgnoreCase) ?? false)
        .Single()
        .Attribute("value").Value;

    return commodityElement
        .Descendants("ContractMonths").Elements("Month")
            .Select(v => symbol + " " + SymbolHelpers.GetSymbolContractMonthLetter(v.Attribute("value")?.Value) + yrLastDigit + " Comdty")
            .ToList();
}
...