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

发布于 2024-12-12 00:59:19 字数 1398 浏览 0 评论 0原文

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

I have an xml file that returns a set of elements that are unique by a attribute value. This presents a problem, as I can not select a node by its name:

<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. Is there a way to select a node based on the value of its attribute? In the below example, can I get the arr node if the @name attribute = "ATR_FamilyName"? In xpath it would be:

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

here is my linq to xml query:

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....                              
        };

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

随心而道 2024-12-19 00:59:19

与 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 属性,您将收到异常。有时,异常可能会更好 - 如果这表明数据从根本上被破坏并且您想要找出它而不是仅仅与值不匹配。

(将 XElement 转换为 string 也是如此。)

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:

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). If you use the Value property, you'll get an exception. 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.)

霊感 2024-12-19 00:59:19

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

With LINQ you can easily select just the nodes that have a specified attribute, like this:

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
            };
预谋 2024-12-19 00:59:19

像这样使用 XElement

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

抱歉使用手机打字

Use XElement like this:

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

Sorry for typing from cell phone

可遇━不可求 2024-12-19 00:59:19

由于 rt 是您各自的 XElement 根,您还可以仅使用扩展方法 XPathSelectElement 像这样:

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

With rt being your respective XElement root, you could also just use the extension method XPathSelectElement like so:

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文