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

时间:2019-07-17 18:24:49

标签: c# xml linq

鉴于以下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>

我认为以下内容可能会给我我想要的东西,但我认为我试图将过滤器的等级应用得太高(着眼于CELL的选择)。没有筛选器,我的列表创建按预期的方式。设置好过滤器后,没有其他元素可供选择。

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();

我认为'.Where'必须应用于d,但不确定如何。感谢您的关注。

编辑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();

1 个答案:

答案 0 :(得分:0)

尝试以下操作:

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


}