c# - 在 LINQ 中查询所有嵌套的 XML 类型

标签 c# linq linq-to-xml

我有一个由 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() 
    };

这可行,但它将报告类型(TrdCaptRptTrdCaptRptAck 等)硬编码到查询中。如何修改查询,以便无论将来可能添加什么报告类型,我都可以运行一个通用查询,它会告诉我每个 TrdTypTradSubType 对应是否为TrdCaptRptTrdCaptRptAck等?

所以问题是关于如何对嵌套属性进行报告,如果它们存在,按报告类型索引。

对于给定的 XML 示例,我希望得到这样的结果:

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

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

如果有任何其他属性,它也会给出这些属性的计数报告。

--

Response to Jeff : 谢谢,非常非常接近。我意识到我没有提供足够的信息。 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。

谢谢。

最佳答案

因此,如果我了解您在问题中想要的内容,我相信这就是您想要的:

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

This will create a dictionary of dictionaries of the counts of your attribute/value pairs per element type. It counts all attributes for all elements however. I couldn't tell which elements or attributes you wanted to count.


If you want to go further down the element hierarchy, change the last Elements() call to Descendants() and that will include all the nested elements and their attribute counts.

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

关于c# - 在 LINQ 中查询所有嵌套的 XML 类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6498359/

相关文章:

c# - LINQ to SQL 关联抛出 null 异常

C# LINQ 查询 - 无隐式转换错误

c# - 生成排列的此 LINQ 代码的说明

c# - XDocument 到 XElement

c# - 使用itextsharp使用哪个xaml控件显示pdf文件?

c# - 使用 stringbuilder 动态创建控件

c# - CancellationToken.ThrowIfCancellationRequested 后的故障与取消任务状态

c# - LINQ 在内部集合上相交

c# - XElement => 在运行时添加子节点

c# - 将 LINQ 转换为 XML