【问题标题】:Linq to XML selecting a node bases on a attribute valueLinq to XML 根据属性值选择节点
【发布时间】:2011-10-25 16:26:24
【问题描述】:

我有一个 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 填充“产品”类。我可以按位置选择元素,但是如果节点不存在,这将成为一个问题。有没有办法根据其属性的值来选择一个节点?在下面的示例中,如果@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....                              
              };   

【问题讨论】:

    标签: c# linq linq-to-xml


    【解决方案1】:

    类似于 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") 的调用结果使用强制转换意味着如果有任何元素具有该属性,则强制转换将导致空引用(不等于字符串文字)。如果你使用Value 属性,你会得到一个异常。有时例外可能会更好 - 如果这表明数据从根本上被破坏并且您想要找出它而不是仅仅与值不匹配。

    XElementstring 的演员表也是如此。)

    【讨论】:

    • 感谢 Jon 对选角的解释。我遇到了并非所有节点都具有该属性并且它抛出异常的情况,因为我使用了 .Value 而不是强制转换;这个固定它。
    【解决方案2】:

    使用 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
                };
    

    【讨论】:

      【解决方案3】:

      像这样使用XElement

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

      抱歉用手机打字

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-09-09
        • 2016-12-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多