2013-12-17 46 views
2

我想用XDocument來解析xml文檔,但是我對XML很陌生,以前只使用過JSON。到目前爲止,我可以解析每個報告名稱,但我試圖解析參數列表。當沒有節點區分不同參數時,如何解析參數列表?使用XDocument和LINQ解析XML和元素對

var reports = xml.Descendants("Report").Select(reportElement => new 
{ 
    Name = reportElement.Attribute("Name").Value, 
    Parameters = reportElement.Descendants("ParameterList").Select(parameter => new 
    { 
    }) 
}); 

XML:

<ReportList> 
    <Report Name="JobNotClose"> 
     <ParameterList> 
      <Name>@StationCode</Name><Value>LAX</Value> 
      <Name>@ShipmentType</Name><Value>SE|SI</Value> 
     </ParameterList> 
    </Report> 
    <Report Name="JobWithoutSales"> 
     <ParameterList> 
      <Name>@StationCode</Name><Value>PA</Value> 
      <Name>@JobDateFrom</Name><Value>2013-10-1</Value> 
      <Name>@JobDateTo</Name><Value>2013-10-31</Value> 
     </ParameterList> 
    </Report> 
</ReportList> 
+1

那xml看起來有點小狗給我。參數條目是不是應該是? – Alex

+0

看到這就是我問的,但沒有這將如何被格式化。如果這是一個節點,我只是使用'.Descendants()'我真的不知道如何處理它像這樣構造 – ChaoticLoki

回答

2

您可以使用Enumerable.Zip合併與參數的參數名稱序列值序列:

var reports = from r in xml.Root.Elements("Report") 
       let parameters = r.Element("ParameterList") 
       select new { 
        Name = (string)r.Attribute("Name"), 
        Parameters = parameters.Elements("Name") 
             .Zip(parameters.Elements("Value"), 
               (n,v) => new { 
                Name = (string)n, 
                Value = (string)v 
               }) 
       }; 

這給了以下報告集合:

[ 
    { 
    "Name": "JobNotClose", 
    "Parameters": [ 
     { 
     "Name": "@StationCode", 
     "Value": "LAX" 
     }, 
     { 
     "Name": "@ShipmentType", 
     "Value": "SE|SI" 
     } 
    ] 
    }, 
    { 
    "Name": "JobWithoutSales", 
    "Parameters": [ 
     { 
     "Name": "@StationCode", 
     "Value": "PA" 
     }, 
     { 
     "Name": "@JobDateFrom", 
     "Value": "2013-10-1" 
     }, 
     { 
     "Name": "@JobDateTo", 
     "Value": "2013-10-31" 
     } 
    ] 
    } 
] 
0

也許這會工作。

您可以使用XNode.ElementsAfterSelf將ParameterList元素作爲IEnumerable。 然後遍歷結果集並假定元素是成對的。

這實際上會給你一種方法來解析出現在ParameterList中的元素的順序,而不用擔心.Descendants搞亂了順序。

當然,這裏的一個重要假設是元素總是成對的。

1

試試這個(和嘗試我的意思是使用):

var reports = xml.Descendants("Report").Select(reportElement => new 
{ 
    Name = reportElement.Attribute("Name").Value, 
    Parameters = reportElement.Descendants("ParameterList").Select(parameter => 
    { 
     List<string> names = parameter.Elements("Name").Select(x=>x.Value).ToList(); 
     List<string> values = parameter.Elements("Value").Select(x=>x.Value).ToList(); 

     List<object> pairs=new List<object>(); 

     for (int i = 0; i < names.Count; i++) 
     { 
      pairs.Add(new { Name = names[i], Value = values[i] }); 
     } 

     return pairs;      
    }).ToList() 
}).ToList(); 

您可以刪除這兩個ToList()電話。它只是使測試更容易。當然,在您的XML中,可能存在<Name> <Value>標籤並不總是完整的(即Name而沒有Value)。您可以在執行for循環之前檢查。

編輯:另一種:

Dictionary<string, List<Tuple<string, string>>> rep = new Dictionary<string, List<Tuple<string, string>>>(); 

foreach (XElement report in xml.Elements("Report")) 
{ 
    rep.Add(report.Attribute("Name").Value, new List<Tuple<string, string>>()); 

    List<string> names = report.Elements("ParameterList").FirstOrDefault().Elements("Name").Select(x => x.Value).ToList(); 
    List<string> values = report.Elements("ParameterList").FirstOrDefault().Elements("Value").Select(x => x.Value).ToList(); 

    for (int i = 0; i < names.Count; i++) 
    { 
     rep[report.Attribute("Name").Value].Add(new Tuple<string, string>(names[i], values[i])); 
    } 
} 
+0

這不會使參數成爲一個列表清單嗎?我可能從參數的開頭寫錯了。據我的理解,每個報告將只包含一個ParameterList節點,並在其中多個對 – ChaoticLoki

+0

@ChaoticLoki,是的,它確實使它成爲一個列表清單。這是這種方法的缺點。還有其他的方法。這個建立在你的邏輯之上。 –