【问题标题】:XML & Lambda - accessing fields that don't implement the IEnumerable interfaceXML & Lambda - 访问不实现 IEnumerable 接口的字段
【发布时间】:2018-01-07 02:46:34
【问题描述】:

我正在使用 Linq/Lambda 以标准方式将输出写入 XML 文件:

new XElement("Employees",
            from emp in empList
            select new XElement("Employee",
                         new XAttribute("ID", emp.ID),
                           new XElement("FName", emp.FName),
                           new XElement("LName", emp.LName),
                           new XElement("DOB", emp.DOB),
                           new XElement("Sex", emp.Sex)
                       ));

实际上我遇到的问题是我的 emp 类包含不实现 IEnumerable 接口的字段,但它们本身也包含字段(例如,想象一下,emp 包含一个“WorkHistory”字段,它本身包含一组与投诉、表扬等相关的字段)。后面的这些字段在 XML 模式中是可选的(并且不重复)。

在给定 Linq/Lambda 框架的情况下,是否有任何方法可以检查它们是否已设置(即它们是否为空)?如果未设置,则需要不存在等效的 XML 节点。

希望这是有道理的。我是 Linq/Lambda 的新手,如果听起来很困惑,我很抱歉。

【问题讨论】:

    标签: c# xml linq lambda


    【解决方案1】:

    我写了一个简单的驱动程序。以后发帖请关注this guide

    您可以这样做several ways。出于好奇,我尝试了 linq:

    using System;
    using System.Linq;
    using System.Xml.Linq;
    using System.Collections.Generic;
    
    namespace Rextester
    {
        public class Program
        {
            public static void Main(string[] args)
            {
                var empList = new List<Employee>();
                for (int i=0; i<10; i++) {
                    empList.Add(GenerateTestEmployee(i));
                }
    
                var xmlConverter = new XmlConverter();
                var employeesNode = new XElement(
                    "Employees",
                    empList.Select(emp => xmlConverter.Convert(emp))
                );
    
                Console.WriteLine(employeesNode.ToString());
            }
    
            private static Employee GenerateTestEmployee(int seed) {
                return new Employee() {
                    ID = Guid.NewGuid(),
                    FName = seed.ToString(),
                    LName = "Example",
                    DOB = DateTime.UtcNow.AddYears(-20).AddYears(-seed),
                    Sex = seed % 2 == 0 ? "Male" : "Female",
                    WorkHistory = GenerateTestWorkHistory(seed)
                };
            }
    
            private static WorkHistory GenerateTestWorkHistory(int seed) {
                if (seed % 7 == 0) {
                    return null;
                }
                return new WorkHistory() {
                    Complaints = Enumerable.Repeat("Complaint!", seed % 2).ToList(),
                    Commendations = Enumerable.Repeat("Commendation!", seed % 3).ToList()
                };
            }
        }
    
        public class Employee {
            public Guid ID { get; set; }
            public string FName { get; set; }
            public string LName { get; set; }
            public DateTime DOB { get; set; }
            public string Sex { get; set; }
            public WorkHistory WorkHistory { get; set; }
    
        }
    
        public class WorkHistory {
            public List<string> Complaints { get; set; }
            public List<string> Commendations { get; set; }
        }
    
        public class XmlConverter {
            public XElement Convert(Employee emp) {
                var attributes = new List<XAttribute> { 
                    new XAttribute("ID", emp.ID)
                };
                var elements = new List<XElement> {
                    new XElement("FName", emp.FName),
                    new XElement("LName", emp.LName),
                    new XElement("DOB", emp.DOB),
                    new XElement("Sex", emp.Sex)
                };
                var workHistory = Convert(emp.WorkHistory);
                if (workHistory != null) {
                    elements.Add(workHistory);
                }
                return new XElement("Employee", attributes, elements);
            }
    
            private XElement Convert(WorkHistory hist) {
                if (hist == null) {
                    return null;
                }
    
                var elements = new List<XElement>();
                if (hist.Complaints != null && hist.Complaints.Any()) {
                    var complaints = new XElement(
                       "Complaints",
                       hist.Complaints.Select(comp => new XElement("Complaint", comp))
                   );
                   elements.Add(complaints);
                }
                if (hist.Commendations != null && hist.Commendations.Any()) {
                    var commendations = new XElement(
                       "Commendations",
                       hist.Commendations.Select(comm => new XElement("Commendation",comm))
                   );
                   elements.Add(commendations);
                }
                return elements.Any() ? new XElement("WorkHistory", elements)
                                      : null;
            }
        }
    }
    

    祝你好运!

    PS:我发现this online IDE 对测试 sn-ps 很有帮助。

    【讨论】:

      【解决方案2】:

      使用方法语法,而不是查询语法,您可以逐步构建 Employee 元素,仅在需要时添加可选的子元素:

      new XElement("Employees",
          empList.Select(emp => {
              var xe = new XElement("Employee",
                  new XAttribute("ID", emp.ID),
                  ....
              ));
      
              // do further checks and add optional child elements accordingly
              if (emp.WorkHistory != null) xe.Add(new XElement(...));
      
              // return the final result
              return xe;
          })
      )
      

      【讨论】:

      • 这是否将 WorkHistory 添加为 Employee XElement 的子元素?谢谢!
      • @user5956088 是的
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-25
      • 2014-12-25
      • 2023-03-04
      • 1970-01-01
      • 2015-01-15
      • 2016-01-14
      相关资源
      最近更新 更多