Linq to XML根据属性值选择节点

Phi*_*yNJ 10 c# linq linq-to-xml

我有一个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> 
Run Code Online (Sandbox Code Playgroud)

我正在使用linq来填充"Product"类.我可以按位置选择元素,但如果节点不存在,这就成了问题.有没有办法根据其属性的值选择节点?在下面的示例中,如果@name属性="ATR_FamilyName",我可以获取arr节点吗?在xpath中它将是:

doc/arr[@name = 'ATR_FamilyName']/str
Run Code Online (Sandbox Code Playgroud)

这是我的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....                              
              };   
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 21

像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....                              
}; 
Run Code Online (Sandbox Code Playgroud)

请注意,对调用结果使用强制转换Attribute("name")意味着如果有任何元素没有该属性,则强制转换将导致空引用(不等于字符串文字).如果您使用该Value属性,您将获得一个例外.有时异常可能更好 - 如果这表明数据从根本上被打破并且您想要找到它而不是仅仅不匹配该值.

(同样是对的演员真正XElement到string.)


as-*_*cii 6

使用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
            };
Run Code Online (Sandbox Code Playgroud)