简体   繁体   English

从文本文档在C#中创建XML层次结构

[英]Create XML Hierarchy in C# from Text Doc

I need to take in a text document from a server and create an XML hierarchy from it in order to use it in a C# program. 我需要从服务器中获取一个文本文档,并从中创建一个XML层次结构,以便在C#程序中使用它。

It will be an organizational hierarchy. 这将是一个组织层次结构。 Here is the same of the text file: 这与文本文件相同:

EmployeeID; Employee Name; SupervisorID

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

Where the above relationships would be: 以上关系将是:

Bob's boss is Jill. 鲍勃的老板是吉尔。 Mark's boss is Bob, and Jill has no boss. 马克的老板是鲍勃,而吉尔没有老板。

I want to create an XML file from that data to look something like this: 我想从该数据创建一个XML文件,如下所示:

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

I don't know if this makes sense, because I have never worked with C# or XML before. 我不知道这是否有意义,因为我以前从未使用过C#或XML。
Feel free to change how the tags are named, the main things I will need to do: 随意更改标签的命名方式,这是我需要做的主要事情:

  1. Be able to get the names of everyone supervised by the same person. 能够获得由同一个人监督的每个人的姓名。 (Ex: Mark would want Mark and Ann) (例如:马克会想要马克和安)

  2. Be able to get the names of all supervisors above an employee (Ex: Mark's would be Bob and Jill) 能够获得员工之上的所有主管的姓名(例如:Mark是Bob和Jill)

  3. Be able to get the names of all people under then (Ex: Mark would have nobody, Jill would have everybody, Bob would have Mark and Ann) 能够获得当时所有人的姓名(例如:马克将没有任何人,吉尔将拥有所有人,鲍勃将拥有马克和安)

I've looked at XElement and XDoc and various tutorials and SO questions but most of the SO questions are too advanced for me at this point, and most of the tutorials aren't trying to create a hierarchy like mine. 我看过XElement和XDoc以及各种教程和SO问题,但目前大多数SO问题对我来说太高级了,并且大多数教程都没有尝试创建像我这样的层次结构。

Define a class Employee: 定义一个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();
    }
}

then parse your input: 然后解析您的输入:

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

and then set the minions for each: 然后为每个设置奴才:

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

And produce the XML like this: 并生成如下所示的XML:

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

If it's not obvious this code is quite dirty and unreliable, add some checks and cleanups 如果不太明显,则此代码很脏且不可靠,请添加一些检查和清理

Employee class: 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())));
    }
}

And parsing logic: 并解析逻辑:

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

Result that I received from that code with your sample input: 我从该代码收到的结果连同您的示例输入:

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

I think that structure is better than you suggested. 我认为这种结构比您建议的要好。 However, you can easily modify XML structure by modifying ToXml method within Employee class. 但是,您可以通过修改Employee类中的ToXml方法来轻松地修改XML结构。 Following one would give output you suggested: 以下是您建议的输出:

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

Result: 结果:

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

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

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