2011-08-21 73 views
2

我得到了一個XML,我試圖用LINQ to XML解析並將其轉換爲匿名的對象列表。要做到這一點,我想出了下面的代碼片段:使用LINQ讀取XML時防止重複元素訪問

var res = doc 
      .Root 
      .Elements("Record") 
      .Elements("Term") 
      .Select(term => new 
      { 
       LanguageCode = term.Attribute("languageCode").Value, 
       ConceptNumber = Convert.ToInt32(term.Attribute("conceptNumber").Value), 
       IsHidden = Convert.ToBoolean(term.Attribute("hidden").Value), 
       Label = term.Value, 

       InputDate = DateTime.Parse(term.Parent.Element("InputDate").Value), 
       LastUpdate = DateTime.Parse(term.Parent.Element("LastUpdated").Value) 
      }).ToList(); 

請注意InputDate & LASTUPDATE部分。正如你看到的,我必須訪問父節點(比如,term.Parent),以便我可以訪問這2個元素,這看起來很亂。是否有任何方法可以聲明term.Parent一次並反覆使用它來提取這些屬性?

這裏是XML的一個片段,我想讀:

<Record> 
    <Term languageCode="Prs" conceptNumber="10" hidden="False">Whatever</Term> 
    <Status>Approved</Status> 
    <Frequency>0</Frequency> 
    <InputDate>12/30/1899</InputDate> 
    <LastUpdate>10/25/2009</LastUpdate> 
</Record> 

謝謝

+0

正如我在這裏看到了你的第一個問題。請標記正確答案或回答當前答案,如果有錯誤。謝謝。 –

回答

6

您需要使用let clause。它在查詢內部創建一個新的變量並允許使用它多次。

你的情況,這將是

var res = (from term in doc.Root.Elements("Record").Elements("Term") 
      let parent = term.Parent 
      select new 
      { 
       LanguageCode = term.Attribute("languageCode").Value, 
       ConceptNumber = Convert.ToInt32(term.Attribute("conceptNumber").Value), 
       IsHidden = Convert.ToBoolean(term.Attribute("hidden").Value), 
       Label = term.Value, 
       InputDate = parent.Element("InputDate").Value, 
       LastUpdate = parent.Element("LastUpdated").Value 
      }).ToList(); 

需要注意的是其在純LINQ的語法,讓你表達自己的想法比你的問題使用類似的擴展方法更清晰的代碼。

+0

嗯,我其實想用LINQ方法。以下答案是否與您已經提供的表達式相對應? –

+0

@Simon Max,我給你一個使用純LINQ的答案。正如BrokenGlass所說,該代碼使用擴展方法(Select,SelectMany,Where等)。我沒有看到任何理由直接使用這種方法,而不是LINQ語法(它可以清楚地表達你的想法)。 「......以下答案......」 - 答案是什麼?另一個由BrokenGlass? –

1

您可以在投影引入一個匿名類(這是類似於let引擎蓋下做),然後使用SelectMany()使用額外的屬性扁平化:

var results = doc.Elements("Record") 
       .Select(x => new 
        { 
        Terms = x.Elements("Term"), 
        InputDate = DateTime.Parse(x.Element("InputDate").Value), 
        LastUpdate = DateTime.Parse(x.Element("LastUpdate").Value) 
        }) 
       .SelectMany(x => x.Terms, (record,term) => new 
       { 
        LanguageCode = term.Attribute("languageCode").Value, 
        .. 
        InputDate = record.InputDate, 
        LastUpdate = record.LastUpdate 
       });