2011-10-25 90 views
6

我有一個xml文件,它返回一組由屬性值唯一的元素。這就提出了一個問題,因爲我不能選擇其名稱的節點:Linq to XML根據屬性值選擇節點

<doc> 
    <float name="score">1.2873721</float> 
    <arr name="2_category"> 
     <long>3021</long> 
    </arr> 
    <arr name="ATR_FamilyName"> 
     <str>Some Cookbook </str> 
    </arr> 
    <arr name="ATR_IsFamily"> 
     <str>0</str> 
    </arr> 
    <arr name="ATR_SellPrice"> 
     <str>49.95</str> 
    </arr> 
    <arr name="ATR_VendorId"> 
     <str>ABC</str> 
    </arr> 
    <arr name="ATR_VendorName"> 
     <str>WROX</str> 
    </arr>  
</doc> 

我使用LINQ to填充一個「產品」類。我可以按位置選擇元素,但如果節點不存在,則會成爲問題。有沒有辦法根據它的屬性值來選擇一個節點?在下面的例子中,如果@name屬性=「ATR_FamilyName」,我可以得到arr節點嗎?在XPath這將是:

doc/arr[@name = 'ATR_FamilyName']/str 

,這裏是我的LINQ to XML查詢:

var query = from rt in results 
    where (String)rt.Descendants().ElementAt(5).Element("str").Value == "0" 
    select new Product.Product 
      { 
       FamilyName = (String)rt.Descendants().ElementAt(3).Value 
       // doc/arr[@name = 'ATR_FamilyName']/str - select Family Name is arr/@name 'ATR_FamilyName'        
       MorePropertiestoset....        
       }; 

回答

17

與AS-CII的回答一樣,但不使用查詢表達式(除了外部表達式),並且使用XAttribute的轉換,並在匿名類型中選擇str元素值:

select new Product.Product 
{ 
    FamilyName = rt.Descendants("arr") 
        .Where(x => (string) x.Attribute("name") == "ATR_FamilyName") 
        .Select(x => (string) x.Element("str")) 
        .FirstOrDefault(), 
    MorePropertiesToSet....        
}; 

注意的是,使用呼叫來Attribute("name")結果的演員意味着如果有哪個有屬性的任何元素,演員將導致空引用(ISN不等於字符串文字)。如果您使用Value屬性,則會發生異常。有時例外情況可能會更好 - 如果這表明數據基本上已損壞,並且您想了解它而不是僅僅匹配該值。

(同樣是爲XElement的演員來string真的。)

+0

謝謝喬恩打字 - 你釘。我適合每個人的快速回復 – PhillyNJ

+0

Thx對於演員Jon的解釋。我遇到了並非所有節點都具有該屬性的情況,它正在拋出異常,因爲我使用了.Value而不是cast;這個fidex吧。 –

5

使用LINQ可以方便地選擇只具有指定屬性的節點,就像這樣:

var query = from node in results.Descendants("arr") // I believe you could use results.Elements("arr") here 
      where node.Attribute("name").Value == "ATR_FamilyName" 
      select new Product 
      { 
       FamilyName = node.Element("str").Value 
      }; 
2

使用XElement這樣的:

from rt in results.descendants("<node name>") 
where rt.attribute(attribute name).value == "specified value" 
select rt 

對不起,從手機