2011-06-27 102 views
2
所有嵌套的XML類型

我有一個包含的XML行的字符串,看起來像這樣:查詢在LINQ

<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。

謝謝。

+0

我已經刪除了註釋掉的代碼,它只是太多的噪音。因此,如果我正確理解您的問題,您只需要計算每個元素名稱的'FIXML'元素下的元素中出現了多少個屬性? –

+0

p.s.只是一個提示,如果你想得到提供答案的人的注意,請對答案留言。我沒有收到任何有關您發佈的更新通知或任何其他答案的通知。我通常會注意到你的更新,但我遇到了一些連接問題,所以我無法像往常一樣頻繁地檢查SO。我會通過更新我的答案來解決您的更新。 –

回答

0

所以,如果我理解你在你的問題想要的東西,我相信這是你想要什麼:

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