2014-04-07 67 views
0

有很多像這樣的問題,但是這個是非常獨特的,我可以向你保證!我需要一個通用的解決方案來將XML數據平鋪到兩列網格(Field,Value),但真正的挑戰在於XML數據的層次結構對於每個響應都是不同的!使用C#展開XML到DataGridView/Linq

這是以XML格式存儲在數據庫中的審計數據,我無法更改這些響應的結構,但需要處理任何可能的層次結構,並將結果以簡單的網格顯示給用戶。

下面是XML結構的一個樣本:

<xml> 
    <results> 
    <resultsDTO> 
     <reportid>173601</reportid> 
     <results> 
     <displayName>Item 1</displayName> 
     <someParameter>blahblah</someParameter> 
     <hidden>false</hidden> 
     <values> 
      <value>10</value> 
      <resultType>PERCENTAGE</resultType> 
     </values> 
     <values> 
      <value>some.pdf</value> 
      <resultType>PDF</resultType> 
     </values> 
     <values> 
      <value>Findings of Item 1</value> 
      <resultType>FINDINGS</resultType> 
     </values> 
     </results> 
     <results> 
     <displayName>Item 2</displayName> 
     <someParameter>blahblah</someParameter> 
     <hidden>false</hidden> 
     <values> 
      <value>20</value> 
      <resultType>PERCENTAGE</resultType> 
     </values> 
     <values> 
      <value/> 
      <resultType>PDF</resultType> 
     </values> 
     <values> 
      <value>Findings of Item 2</value> 
      <resultType>FINDINGS</resultType> 
     </values> 
     </results> 
     <reportTexts> 
     <value/> 
     <resultType>HISTORY</resultType> 
     </reportTexts> 
     <reportTexts> 
     <value>Some info here.</value> 
     <resultType>INFORMATION</resultType> 
     </reportTexts> 
    </resultsDTO> 
    </results> 
</xml> 

正如你可以看到從XML總有一個「與resultType」和「價值」在同一水平,但是我需要一種方法來遍歷通過這個XML而不定義任何硬編碼路徑(XML/Results/ResultsDTO/Results/Values /),它們將在任何級別找到這些resultTypes和值,並處理一些特殊的數據規則。

我試圖讓這些值到一個GridView的輸出是這樣的:

[Field], [Value] 
Item 1 - Percentage, 10 
Item 1 - Findings, Findings of Item 1 
Item 2 - Percentage, 20 
Item 2 - Findings, Findings of Item 2 
History, NULL 
Information, Some info here. 

這是我這是顯示的我想要實現半流代碼:

XDocument doc = XDocument.Load(@"XMLFile1.xml"); 
var query = from c in doc.Descendants("xml").Elements("results").Elements("resultsDTO").Elements("results").Elements("values").Where(n => n.Element("resultType").Value != "PDF") 
      select new 
      { 
       Field = c.Parent.Element("displayName") == null ? c.Element("resultType").Value : c.Parent.Element("displayName").Value + " - " + c.Element("resultType").Value, 
       Value = c.Element("value").Value   
      }; 
dataGridView1.DataSource = query.ToList(); 

我禁止顯示「PDF」resultType,並將displayName附加到resultType(如果它存在於父項中)!因爲它不適用於其他節點。

這是目前唯一得到的值在XML /業績/ ResultsDTO /業績/值/而不是值XML /業績/ ResultsDTO/ReportTexts內。

任何幫助將不勝感激!謝謝。

回答

1

你是對的大部分。所有你需要做的是:

  1. 聯盟reportTexts元素的繼承者。
  2. 後裔不需要你遍歷的路徑。你可以給任何起始路徑。

使用以下查詢:

var query = from c in doc.Descendants("values").Union(doc.Descendants("reportTexts")).Where(n => n.Element("resultType").Value != "PDF") 
      select new 
      { 
       Field = c.Parent.Element("displayName") == null ? c.Element("resultType").Value : c.Parent.Element("displayName").Value + " - " + c.Element("resultType").Value, 
       Value = c.Element("value").Value // you can replace "" by null here 
      }; 

輸出如下:

[Field], [Value] 
Item 1 - Percentage, 10 
Item 1 - Findings, Findings of Item 1 
Item 2 - Percentage, 20 
Item 2 - Findings, Findings of Item 2 
History, "" 
Information, Some info here. 
+0

感謝您的後人解釋,這個工作奇妙! – bfritz