【问题标题】:Create XML Hierarchy in C# from Text Doc从 Text Doc 在 C# 中创建 XML 层次结构
【发布时间】:2013-02-16 09:44:16
【问题描述】:

我需要从服务器获取一个文本文档并从中创建一个 XML 层次结构,以便在 C# 程序中使用它。

这将是一个组织层次结构。这是文本文件的相同内容:

EmployeeID; Employee Name; SupervisorID

1; Bob; 3
2; Mark; 1
3; Jill; 0
4; Ann ; 1

上述关系的位置:

鲍勃的老板是吉尔。 Mark 的老板是 Bob,Jill 没有老板。

我想从该数据创建一个 XML 文件,看起来像这样:

<Employee> Jill
   <Employee> Bob
      <Employee> Mark </Employee>
      <Employee> Ann </Employee>
  </Employee>
</Employee>

我不知道这是否有意义,因为我以前从未使用过 C# 或 XML。
随意更改标签的命名方式,我需要做的主要事情:

  1. 能够获取由同一个人监督的每个人的姓名。 (例如:马克想要马克和安)

  2. 能够获取员工之上所有主管的姓名(例如:Mark 的姓名为 Bob 和 Jill)

  3. 能够获取当时所有人的姓名(例如:Mark 将没有任何人,Jill 将拥有所有人,Bob 将拥有 Mark 和 Ann)

我查看了 XElement 和 XDoc 以及各种教程和 SO 问题,但目前大多数 SO 问题对我来说太高级了,而且大多数教程都没有尝试创建像我这样的层次结构。

【问题讨论】:

    标签: c# xml xml-parsing xml-serialization linq-to-xml


    【解决方案1】:

    定义一个Employee类:

    public class Employee{
        [XmlIgnore]
        public int ID{get;set;}
    
        [XmlIgnore]
        public int BossID{get;set;}
    
        [XmlText]
        public string Name{get;set;}
    
        [XmlElement("Employee")
        public Employee[] Minions{get;set;}
        public SetMinions(List<Employee> list){
           Minions = list.Where(e=>e.BossID==ID).ToArray();
        }
    }
    

    然后解析您的输入:

    List<Employee> list = File.ReadAllLines("MyInputFile.txt")
       .Select(l=>new Emplyee(){
            ID = l.Split(';')[0],
            Name= l.Split(';')[1],
            BossID = l.Split(';')[2]}).ToList();
    

    然后为每个设置小兵:

    list.ForEach(e=>e.SetMinions(list));
    

    并像这样生成 XML:

      XmlSerializer xser = new XmlSerializer(typeof(Employee));
      xser.Serialize(File.OpenWrite("output.txt", list.First(e=>e.BossID==0)));
    

    如果不是很明显这段代码很脏且不可靠,请添加一些检查和清理

    【讨论】:

    • @user2019260 现在可以了,但 XML 可能需要更多的爱才能看起来完全符合您的要求
    【解决方案2】:

    Employee类:

    public class Employee
    {
        public Employee()
        {
            Subordinates = new List<Employee>();
        }
    
        public int Id { get; set; }
        public string Name { get; set; }
        public int SupervisorId { get; set; }
        public List<Employee> Subordinates { get; private set; }
    
        public XElement ToXml()
        {
            return new XElement("Employee",
                       new XElement("Id", Id),
                       new XElement("Name", Name),
                       new XElement("Subordinates", Subordinates.Select(s => s.ToXml())));
        }
    }
    

    以及解析逻辑:

    // dictionary as a storage for data read from file
    var Employees = new Dictionary<int,Employee>();
    
    // file reading
    var file = File.Open("Input.txt", FileMode.Open);
    using (var reader = new StreamReader(file))
    {
        reader.ReadLine();
        while (!reader.EndOfStream)
        {
            string line = reader.ReadLine();
            string[] fields = line.Split(';');
    
            var newEmployee = new Employee { Id = int.Parse(fields[0]), Name = fields[1].Trim(), SupervisorId = int.Parse(fields[2]) };
            Employees.Add(newEmployee.Id, newEmployee);
        }
    }
    
    // filling Subordinates within every employee
    foreach (var emp in Employees.Values)
    {
        if (Employees.ContainsKey(emp.SupervisorId))
            Employees[emp.SupervisorId].Subordinates.Add(emp);
    }
    
    // taking first (root) employee by selecting the one with supervisorId == 0
    var first = Employees.Values.First(e => e.SupervisorId == 0);
    
    // XML generation
    var xml = first.ToXml();
    

    我从该代码中收到的带有您的示例输入的结果:

    <Employee>
      <Id>3</Id>
      <Name>Jill</Name>
      <Subordinates>
        <Employee>
          <Id>1</Id>
          <Name>Bob</Name>
          <Subordinates>
            <Employee>
              <Id>2</Id>
              <Name>Mark</Name>
              <Subordinates />
            </Employee>
            <Employee>
              <Id>4</Id>
              <Name>Ann</Name>
              <Subordinates />
            </Employee>
          </Subordinates>
        </Employee>
      </Subordinates>
    </Employee>
    

    我认为这种结构比您建议的要好。但是,您可以通过修改Employee 类中的ToXml 方法轻松修改XML 结构。以下一个会给出您建议的输出:

    public XElement ToXml()
    {
        return new XElement("Employee",
                   new XText(Name),
                   Subordinates.Select(s => s.ToXml()));
    }
    

    结果:

    <Employee>Jill
        <Employee>Bob
            <Employee>Mark</Employee>
            <Employee>Ann</Employee>
        </Employee>
    </Employee>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-07
      • 1970-01-01
      • 2017-04-18
      • 1970-01-01
      • 1970-01-01
      • 2019-03-20
      相关资源
      最近更新 更多