简体   繁体   English

C#LINQ to XML-如何基于子元素过滤节点?

[英]C# LINQ to XML - How can I filter nodes based on a child element?

Given the following XML (partial for brevity), I am attempting to only create a new object if the VALUE element for a CELL element where name is C006 is not a given value. 给定以下XML(为简洁起见,它是局部的),我尝试仅在名称为C006的CELL元素的VALUE元素不是给定值的情况下创建一个新对象。

<alv:AREAS>
    <alv:TABLE>
        <alv:COLUMNS>
        <alv:ROWS>
            <ROWNUMBER>9 </ROWNUMBER>
                <ROW type="D" index="0 ">
                <ROW type="D" index="8 ">
                    <CELL name="C001" visible="X" imagefirst="" imageid="0001"/>
                    <CELL name="C002" visible="X">
                        <VALUE>A7F30024579</VALUE>
                    </CELL>
                    <CELL name="C003" visible="X">
                        <VALUE>Xfrmr 40VA,120-24V,single hub,Class II U</VALUE>
                    </CELL>
                    <CELL name="C004" visible="X">
                        <VALUE decimals="0">3</VALUE>
                    </CELL>
                    <CELL name="C005" visible="X">
                        <VALUE>PTO</VALUE>
                    </CELL>
                    <CELL name="C006" visible="X">
                        <VALUE>BANC</VALUE>
                    </CELL>
                </ROW>
        </ROWS>
    </COLUMNS>
</TABLE>

I thought the following might give me what I am looking for but I think I am trying to apply the filter one level too high (focus on the select for CELL). 我认为以下内容可能会为我提供所需的信息,但我认为我试图将过滤器的等级过高(针对CELL的选择)。 Without the filter, my list is created as expected. 没有筛选器,我的列表创建按预期的方式。 With the filter in place, there are no elements to further select. 放置好过滤器后,没有元素可供进一步选择。

var rows = xml.Descendants(ns + "ROWS")
            .SelectMany(row => row.Elements("ROW")).Where(r => r.Attribute("type").Value == "D")
            .Select(c => c.Elements("CELL")).Where(f => f.Attribute("name").Value == "C006").Select(v => v.Element("VALUE").Value != "LEIS"))
            .Select(d => new SAPDevice
            {
                MaterialNumber = d.Where(cell => cell.Attribute("name").Value == "C002").Select(val => val.Element("VALUE").Value).First(),
                PartNumber = d.Where(cell => cell.Attribute("name").Value == "C011").Select(val => val.Element("VALUE").Value).First(),
                Quantity = System.Convert.ToInt32(d.Where(cell => cell.Attribute("name").Value == "C004").Select(val => val.Element("VALUE").Value).First()),
                Price = System.Convert.ToDecimal(d.Where(cell => cell.Attribute("name").Value == "C008").Select(val => val.Element("VALUE").Value).First()),
                Description = d.Where(cell => cell.Attribute("name").Value == "C003").Select(val => val.Element("VALUE").Value).First()//,
                //MaterialType = d.Where(cell => cell.Attribute("name").Value == "C006").Select(val => val.Element("VALUE").Value).First()
            }).ToList();

I think the '.Where' needs to be applied to d but I am unsure how. 我认为'.Where'需要应用于d,但我不确定如何。 Thanks for taking a look. 谢谢参观。

edit 7/19: The following query returns all rows regardless of the filter value: 编辑7/19:以下查询返回所有行,无论过滤器值如何:

var rows = xml.Descendants(ns + "ROWS")
            .SelectMany(row => row.Elements("ROW")).Where(r => r.Attribute("type").Value == "D")
            .Select(c => c.Elements("CELL")).Where(f => !f.Elements("CELL").Any(f1 => ((string)f1.Attribute("name") == "C006") && ((string)f1.Element("VALUE") == "BANC")))
            .Select(d => new SAPDevice
            {
                MaterialNumber = d.Where(cell => cell.Attribute("name").Value == "C002").Select(val => val.Element("VALUE").Value).First(),
                PartNumber = d.Where(cell => cell.Attribute("name").Value == "C011").Select(val => val.Element("VALUE").Value).First(),
                Quantity = System.Convert.ToInt32(d.Where(cell => cell.Attribute("name").Value == "C004").Select(val => val.Element("VALUE").Value).First()),
                Price = System.Convert.ToDecimal(d.Where(cell => cell.Attribute("name").Value == "C008").Select(val => val.Element("VALUE").Value).First()),
                Description = d.Where(cell => cell.Attribute("name").Value == "C003").Select(val => val.Element("VALUE").Value).First()//,
                //MaterialType = d.Where(cell => cell.Attribute("name").Value == "C006").Select(val => val.Element("VALUE").Value).First()
            }).ToList();

Try following : 尝试以下操作:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication120
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            XDocument xml = XDocument.Load(FILENAME);
            XElement root = xml.Root;
            XNamespace ns = root.GetNamespaceOfPrefix("alv");

            var results = xml.Descendants(ns + "ROWS").SelectMany(rows =>
               rows.Descendants("ROW").Where(r => r.Attribute("type").Value == "D")
               .Where(f => !f.Elements("CELL").Any(f1 => ((string)f1.Attribute("name") == "C006") && ((string)f1.Element("VALUE") == "LEIS")))
               .Select(d => new SAPDevice()
               {
                   MaterialNumber = (string)d.Elements("CELL").Where(cell => (string)cell.Attribute("name") == "C002").Select(val => val.Element("VALUE")).FirstOrDefault(),
                   PartNumber = d.Elements("CELL").Where(cell => (string)cell.Attribute("name") == "C011").Select(val => (string)val.Element("VALUE")).FirstOrDefault(),
                   Quantity = (int?)d.Elements("CELL").Where(cell => (string)cell.Attribute("name") == "C004").Select(val => val.Element("VALUE")).FirstOrDefault(),
                   Price = (decimal?)d.Elements("CELL").Where(cell => (string)cell.Attribute("name") == "C008").Select(val => val.Element("VALUE")).FirstOrDefault(),
                   Description = (string)d.Elements("CELL").Where(cell => (string)cell.Attribute("name") == "C003").Select(val => val.Element("VALUE")).FirstOrDefault(),
               //     //MaterialType = d.Elements("CELL").Where(cell => cell.Attribute("name").Value == "C006").Select(val => val.Element("VALUE").Value).First()
               })).ToList();
        }

    }
    public class SAPDevice
    {
        public object test { get; set; }
        public string MaterialNumber { get; set; }
        public string PartNumber { get; set; }
        public int? Quantity { get; set; }
        public decimal? Price { get; set; }
        public string Description { get; set; }
    }


}

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

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