简体   繁体   English

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

[英]Linq to XML selecting a node bases on a attribute value

I have an xml file that returns a set of elements that are unique by a attribute value.我有一个 xml 文件,它返回一组由属性值唯一的元素。 This presents a problem, as I can not select a node by its name:这提出了一个问题,因为我不能通过名称 select 节点:

<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> 

I am using linq to populate a "Product" class. I am able to select the elements by position, however this becomes a problem if the node doesn't exist.我正在使用 linq 来填充“产品”class。我能够通过 position 对元素进行 select,但是如果节点不存在,这将成为一个问题。 Is there a way to select a node based on the value of its attribute?有没有办法根据节点的属性值 select 一个节点? In the below example, can I get the arr node if the @name attribute = "ATR_FamilyName"?在下面的示例中,如果 @name 属性 = "ATR_FamilyName",我可以获取 arr 节点吗? In xpath it would be:在 xpath 中它将是:

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

here is my linq to xml query:这是我的 linq 到 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....                              
        };

Like AS-CII's answer, but without using a query expression (except for the outer one), and with the cast for XAttribute , and selecting the str element value inside an anonymous type: 与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....                              
}; 

Note that the use of a cast for the result of the call to Attribute("name") means that if there are any elements which don't have the attribute, the cast will result in a null reference (which isn't equal to the string literal). 注意,对Attribute("name")的调用结果使用强制转换意味着如果有任何元素没有该属性,则强制转换将导致空引用(不等于字符串文字)。 If you use the Value property, you'll get an exception. 如果使用Value属性,则会出现异常。 Sometimes an exception may be better - if that indicates that the data is fundamentally broken and you want to find out about it rather than just not match the value. 有时异常可能更好 - 如果这表明数据从根本上被打破并且您想要找到它而不是仅仅不匹配该值。

(The same is true for the cast of the XElement to string .) (将XElementstring也是如此。)

With LINQ you can easily select just the nodes that have a specified attribute, like this: 使用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
            };

Use XElement like this: 像这样使用XElement

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

Sorry for typing from cell phone 很抱歉从手机打字

With rt being your respective XElement root, you could also just use the extension method XPathSelectElement like so:由于rt是您各自的 XElement 根,您也可以像这样使用扩展方法XPathSelectElement

rt.XPathSelectElement("descendant::arr[@name = 'ATR_FamilyName']/str")

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM