Запрос для всех вложенных типов XML в LINQ - PullRequest
2 голосов
/ 28 июня 2011

У меня есть строка, состоящая из строк XML, которая выглядит следующим образом:

<FIXML>
  <TrdCaptRpt TrdTyp = "0" TrdSubTyp = "7" />
</FIXML>

<FIXML>
  <TrdCaptRptAck TrdTyp = "0" TrdSubTyp = "7" />
</FIXML>

<FIXML>
  <TrdCaptRptAck TrdTyp = "1" />
</FIXML>

У меня есть несколько специализированных запросов LINQ:

var q =
    from el in clearingMessagesDoc.Elements("ClearingMessages")
                                  .Elements("FIXML")
                                  .Elements("TrdCaptRpt")
                                  .Where(f => f.Attribute("TrdTyp") != null)
    select el.Attribute("TrdTyp");

var t =
    from el in q
    let trdtyp = el.Value
    group trdtyp by trdtyp.Trim() into g
    orderby g.Key descending
    select new { 
        TrdType = g.Key,
        Count = g.Count() 
    };

t.Dump("TrdCaptRpt");

q = from el in learingMessagesDoc.Elements("ClearingMessages")
                                 .Elements("FIXML")
                                 .Elements("TrdCaptRpt")
                                 .Where(f => f.Attribute("TrdSubTyp") != null)
    select el.Attribute("TrdSubTyp");

var t1 =
    from el in q
    let trdSubtyp = el.Value
    group trdSubtyp by trdSubtyp.Trim() into g
    orderby g.Key descending
    select new { 
        TrdSubTyp = g.Key,
        Count = g.Count() 
    };

Это работает, но жестко кодируеттипы отчетов (TrdCaptRpt, TrdCaptRptAck и т. д.) в запросах.Как изменить запросы так, чтобы независимо от того, какие типы отчетов могли быть добавлены в будущем, я могу выполнить обобщенный запрос, который сообщит мне число каждого TrdTyp и TradSubType, соответствующее тому, имеет ли оно значение TrdCaptRpt, TrdCaptRptAck и так далее?

Итак, вопрос в том, как сделать отчет по вложенным атрибутам, если они существуют, проиндексированным по типу отчета.

Я надеюсь получить что-то подобноедля приведенного примера XML:

TrdCaptRpt
    TrdTyp = "0" : 1
    TrdSubTyp = "7" : 1

TrdCaptRptAck 
    TrdTyp = "0" : 1
    TrdTyp = "1" : 1
    TrdSubTyp = "7" : 1

Если бы были какие-либо другие атрибуты, он также предоставил бы отчет о числе этих атрибутов.

-

Ответ Джеффу : Спасибо, это очень, очень близко.Я понял, что я не дал достаточно информации.Файл XML немного сложнее (это лишь малая часть того, как он выглядит для краткости).

<FIXML>
 <TrdCaptRpt TrdTyp = "0" TrdSubTyp = "7">
 <Hdr Snt="2011-05-18T12:26:09-05:00" />
  <RptSide Side="2">
    <Pty ID="GS" R="21"></Pty>
  </RptSide >
 </TrdCaptRpt>
</FIXML>

Другими словами, на каждом уровне может быть много вложенных элементов,Есть ли общий способ получить все это, подсчитав, как часто встречается каждый атрибут, в соответствии с примером, который вы указали индексированным по типу отчета?

Когда я запускаю ваш запрос на XML, который выглядит примерно так,он не опускается ниже TrdCaptRpt.

Спасибо.

1 Ответ

0 голосов
/ 28 июня 2011

Так что, если я понял, что вы хотели в своем вопросе, я считаю, что это то, что вы хотите:

var counts = clearingMessagesDoc
    .Elements("ClearingMessages")
    .Elements("FIXML")
    .Elements()
    .GroupBy(e => e.Name.ToString())
    .ToDictionary(
        g => g.Key,
        g => g.SelectMany(e => e.Attributes())
              .GroupBy(attr => new { Name = attr.Name.ToString(), Value = attr.Value.Trim() })
              .OrderBy(attrg => attrg.Key.Name)
              .ThenBy(attrg => attrg.Key.Value)
              .ToDictionary(
                  attrg => String.Format("{0}=\"{1}\"", attrg.Key.Name, attrg.Key.Value),
                  attrg => attrg.Count()));

Это дает результаты:

Element: TrdCaptRpt
  TrdSubTyp="7": 1
  TrdTyp="0": 1

Это создаст словарь словарей подсчета ваших пар атрибут / значение для каждого типа элемента. Тем не менее, он подсчитывает все атрибутов для всех элементов. Я не мог сказать, какие элементы или атрибуты вы хотели бы посчитать.


Если вы хотите пойти дальше вниз по иерархии элементов, измените последний вызов Elements() на Descendants(), и он будет включать все вложенные элементы и количество их атрибутов.

var counts = clearingMessagesDoc
    .Elements("ClearingMessages")
    .Elements("FIXML")
    .Descendants() // checks ALL elements in the hierarchy
    .GroupBy(e => e.Name.ToString())
    .ToDictionary(
        g => g.Key,
        g => g.SelectMany(e => e.Attributes())
              .GroupBy(attr => new { Name = attr.Name.ToString(), Value = attr.Value.Trim() })
              .OrderBy(attrg => attrg.Key.Name)
              .ThenBy(attrg => attrg.Key.Value)
              .ToDictionary(
                  attrg => String.Format("{0}=\"{1}\"", attrg.Key.Name, attrg.Key.Value),
                  attrg => attrg.Count()));

Это дает следующие результаты:

Element: TrdCaptRpt
  TrdSubTyp="7": 1
  TrdTyp="0": 1
Element: Hdr
  Snt="2011-05-18T12:26:09-05:00": 1
Element: RptSide
  Side="2": 1
Element: Pty
  ID="GS": 1
  R="21": 1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...