【问题标题】:How to generate an XML using XMLSerializer? [duplicate]如何使用 XMLSerializer 生成 XML? [复制]
【发布时间】:2018-01-30 11:26:05
【问题描述】:

我想使用 XMLSerializer 生成一个 XML。我有一个抽象基类,它被其他类继承。

 public abstract class Base
    {
      public string Name {get; set;}
      public int ID {get; set;}

      public Base(string Name, int ID)
      {
         this.Name = Name;
         this.ID = ID;
      }
    }



 public class HR: Base
    {      
      public HR(string Name, int ID): Base(Name,ID)
      {
      }
    }

    public class IT : Base
    {
      public IT(string Name, int ID): Base(Name,ID)
      {
      }
    }

我不知道如何生成格式的 XML

<Employee>
 <HR>
  <Name> </Name>
  <ID> </ID>
 </HR>
 <IT>
  <Name> </Name>
  <ID> </ID>
 </IT>
</Employee>

对于这个含糊的问题,我深表歉意。我以前从未使用过 XMLSerializer,也不知道如何继续使用它。任何帮助将不胜感激。

谢谢

【问题讨论】:

  • 您的课程还有其他一些错误。在Employee 基类中将ID 定义为string,但在HR 类和IT 类中,您将int 作为ID 传递。此外,要调用基类,您应该使用base(Name, ID) 而不是Employee(Name, ID)
  • @nbokmans 道歉。那只是一个错字。我现在已经编辑和更新了代码。感谢您指出。
  • 要让 Xml 序列化程序工作,您的类必须具有公共无参数构造函数。

标签: c# .net xmlserializer


【解决方案1】:

当我阅读您的 xml 时,您似乎想要序列化一个 Employee 列表。 如果您的列表是类的成员(不直接序列化列表),我有一个解决方案。

public abstract class Employee
{
    public string Name { get; set; }
    public int ID { get; set; }
    public Employee(string Name, int ID)
    {
        this.Name = Name;
        this.ID = ID;
    }
}

public class HR : Employee
{
    public HR() : base(null, 0) { } // default constructor is needed for serialization/deserialization
    public HR(string Name, int ID) : base(Name, ID) { }
}
public class IT : Employee
{
    public IT() : base(null, 0) { }
    public IT(string Name, int ID) : base(Name, ID) { }
}

public class Group
{
    [XmlArray("Employee")]
    [XmlArrayItem("HR",typeof(HR))]
    [XmlArrayItem("IT",typeof(IT))]
    public List<Employee> list { get; set; }

    public Group()
    {
        list = new List<Employee>();
    }
}
class Program
{
    static void Main(string[] args)
    {
        Group grp = new Group();
        grp.list.Add(new HR("Name HR", 1));
        grp.list.Add(new IT("Name IT", 2));

        XmlSerializer ser = new XmlSerializer(typeof(Group));
        ser.Serialize(Console.Out, grp);
    }
}

输出是:

<?xml version="1.0" encoding="ibm850"?>
<Group xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Employee>
    <HR>
      <Name>Name HR</Name>
      <ID>1</ID>
    </HR>
    <IT>
      <Name>Name IT</Name>
      <ID>2</ID>
    </IT>
  </Employee>
</Group>

与您想要的输出非常相似,只是在根“组”中多了一个元素。

使用相同的 XmlSerializer(typeof(Group)) 反序列化应该也可以工作。

【讨论】:

  • 非常感谢!!那行得通! :)
【解决方案2】:

我认为您需要使用XmlType 属性来确保您的元素显示为&lt;HR&gt;&lt;IT&gt; 而不是&lt;employee xsi:type="HR"&gt;。下面的工作演示:

public abstract class Employee
{
    public string Name { get; set; }
    public string ID { get; set; }

    public Employee(string Name, string ID)
    {
        this.Name = Name;
        this.ID = ID;
    }
}

public class HR : Employee
{
    public HR(string Name, string ID) : base(Name, ID)
    {
    }


    public HR() : base("No name", "No ID")
    {

    }
}

public class IT : Employee
{
    public IT(string Name, string ID) : base(Name, ID)
    {
    }

    public IT() : base("No name", "No ID")
    {

    }
}   

我为序列化程序添加了默认(无参数)构造函数。

那么你必须有某种包装对象来处理Employees 的列表:

public class Employees
{
    [XmlElement(typeof(IT))]
    [XmlElement(typeof(HR))]
    public List<Employee> Employee { get; set; } //It doesn't really matter what this field is named, it takes the class name in the serialization
}

接下来,您可以使用我评论中的序列化程序代码来生成 XML:

var employees = new Employees
{
    Employee = new List<Employee>()
    {
        new IT("Sugan", "88"),
        new HR("Niels", "41")
    }
};

var serializer = new XmlSerializer(typeof(Employees));
var xml = "";

using (var sw = new StringWriter())
{
    using (XmlWriter writer = XmlWriter.Create(sw))
    {
        serializer.Serialize(writer, employees);
        xml = sw.ToString();
    }
}
Console.WriteLine(xml);

(为清楚起见省略了命名空间)

这将返回以下 XML:

<?xml version="1.0" encoding="UTF-8"?>
<Employees xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <IT>
      <Name>Sugan</Name>
      <ID>88</ID>
   </IT>
   <HR>
      <Name>Niels</Name>
      <ID>41</ID>
   </HR>
</Employees>

【讨论】:

  • 您找到了避免我的解决方案中出现额外级别的方法,谢谢。
  • 非常感谢!!您的解决方案也有效!但我只能将其中一个标记为“已回答”
【解决方案3】:

将 [Serializable] 注解添加到要序列化的类中。

        [System.Serializable]
        public class Base
        {
        public string Name { get; set; }
        public int ID { get; set; }

        public Base(string Name, int ID)
            {
            this.Name = Name;
            this.ID = ID;
            }
        }

要以 XML 格式序列化,请使用以下代码:

        System.Xml.Serialization.XmlSerializer Serializer = new System.Xml.Serialization.XmlSerializer(typeof(Base));
        Base Foo = new Base();
        string xmldata = "";

        using (var stringwriter = new System.IO.StringWriter())
        {
            using (System.Xml.XmlWriter xmlwriter = System.Xml.XmlWriter.Create(stringwriter))
            {
                Serializer.Serialize(xmlwriter, Foo);
                xml = stringwriter.ToString(); // Your XML
            }
        }

要从 XML 反序列化回您的 Base 对象,请使用以下代码:

        System.IO.MemoryStream FooStream = new System.IO.MemoryStream(System.Text.Encoding.UTF8.GetBytes(xml));
        Base Foo;
        Foo = (Base)Serializer.Deserialize(FooStream);

【讨论】:

  • 非常感谢! Employee Foo = new Employee() 会抛出一个错误,因为我认为它不可能创建一个抽象类的实例?
  • 你需要在你的类中有一个默认的构造函数才能让序列化器工作和一个具体的类型。
  • 很抱歉,我没有先阅读抽象部分,你不能创建抽象类的实例,真的。但是您的问题本质上是围绕它的序列化这意味着您将拥有一个对象,上面的代码适用于序列化创建的对象
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-26
  • 1970-01-01
  • 2012-02-12
  • 2011-04-07
相关资源
最近更新 更多