2011-10-25 38 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 

对不起,从手机