在新元素中将 属性 序列化为 Xml 属性

Serialize Property as Xml Attribute in new Element

我有一个简单的class

public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
    public Address Address { get; set; }

    public ICollection<Address> AllAddress { get; set; }
}

public class Address
{
    public string  Street { get; set; }
}

如果我使用默认的 XmlSerializer 序列化 People 实例,那么我将得到

<Person xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <Id>2</Id>
    <Name>FIO FIO IFO</Name>
    <Address>
        <Street>Golden Gate</Street>
    </Address>
</Person>

如何得到这个结果?

<struct n="People">
     <attr n="id">2</attr >
     <attr n="name">FIO FIO IFO</attr >
     <struct n="Address">
         <attr n="street">Golden Gate</attr>
     </struct >
</struct>

看来您必须将 xml 转换为自定义格式,因此您必须在 Person class 对象中实现 IXmlSerializable 接口。

public class Person : IXmlSerializable
{
    public int Id { get; set; }
    public string Name { get; set; }
    public Address Address { get; set; }

    public XmlSchema GetSchema() { throw new NotImplementedException(); }

    public void ReadXml(XmlReader reader)
    {
        while (reader.Read())
        {
            if (reader.Name == "attr" && reader.GetAttribute("n") == "id")
                Id = Convert.ToInt32(reader.ReadInnerXml());

            if (reader.Name == "attr" && reader.GetAttribute("n") == "name")
                Name = reader.ReadInnerXml();

            if (reader.Name == "attr" && reader.GetAttribute("n") == "street")
                Address = new Address { Street = reader.ReadInnerXml() };
        }
    }

    public void WriteXml(XmlWriter writer)
    {
        //Start "struct"
        writer.WriteStartElement("struct");
        writer.WriteAttributeString("n", "People");

        writer.WriteStartElement("attr");
        writer.WriteAttributeString("n", "id");
        writer.WriteString(Id.ToString());
        writer.WriteEndElement();

        writer.WriteStartElement("attr");
        writer.WriteAttributeString("n", "name");
        writer.WriteString(Name.ToString());
        writer.WriteEndElement();

        //Start inner "struct"
        writer.WriteStartElement("struct");
        writer.WriteAttributeString("n", "Address");

        writer.WriteStartElement("attr");
        writer.WriteAttributeString("n", "street");
        writer.WriteString(Address.Street.ToString());
        writer.WriteEndElement();

        //End inner "struct"
        writer.WriteEndElement();

        //End "struct"
        writer.WriteEndElement();
    }
}

并且您可以序列化和反序列化您的 xml 之类的。

Person person = new Person
{
    Id = 2,
    Name = "FIO FIO IFO",
    Address = new Address { Street = "Golden Gate" }
};

//--------------------Serialization----------------------------

XmlSerializer serializer = new XmlSerializer(person.GetType());
using (StreamWriter writer = new StreamWriter(@"Path to xml file"))
{
    serializer.Serialize(writer, person);
}

//--------------------Deserialization----------------------------

using (StringReader stringReader = new StringReader(File.ReadAllText(@"Path to same xml file that generated by above serializer")))
{
    person = (Person)serializer.Deserialize(stringReader);

    Console.WriteLine("Id: " + person.Id);
    Console.WriteLine("Name: " + person.Name);
    Console.WriteLine("Street: " + person.Address.Street);

    Console.ReadLine();
}

序列化输出:

反序列化输出:


备选

您还可以创建自定义方法来读写xml。

1) 写入

public static void WriteXml(Person person, string path)
{
    using (XmlWriter writer = XmlWriter.Create(path))
    {
        //Start "struct"
        writer.WriteStartElement("struct");
        writer.WriteAttributeString("n", "People");

        writer.WriteStartElement("attr");
        writer.WriteAttributeString("n", "id");
        writer.WriteString(person.Id.ToString());
        writer.WriteEndElement();

        writer.WriteStartElement("attr");
        writer.WriteAttributeString("n", "name");
        writer.WriteString(person.Name.ToString());
        writer.WriteEndElement();

        //Start inner "struct"
        writer.WriteStartElement("struct");
        writer.WriteAttributeString("n", "Address");

        writer.WriteStartElement("attr");
        writer.WriteAttributeString("n", "street");
        writer.WriteString(person.Address.Street.ToString());
        writer.WriteEndElement();

        //End inner "struct"
        writer.WriteEndElement();

        //End "struct"
        writer.WriteEndElement();
    }
}

用法:

Person person = new Person
{
    Id = 2,
    Name = "FIO FIO IFO",
    Address = new Address { Street = "Golden Gate" }
};

WriteXml(person, @"Path to xml file");

2) 阅读

public static Person ReadXml(string path)
{
    Person person = new Person();

    using (XmlReader reader = XmlReader.Create(path))
    {
        while (reader.Read())
        {
            if (reader.Name == "attr" && reader.GetAttribute("n") == "id")
                person.Id = Convert.ToInt32(reader.ReadInnerXml());

            if (reader.Name == "attr" && reader.GetAttribute("n") == "name")
                person.Name = reader.ReadInnerXml();

            if (reader.Name == "attr" && reader.GetAttribute("n") == "street")
                person.Address = new Address { Street = reader.ReadInnerXml() };
        }
    }

    return person;
}

用法:

Person result = ReadXml(@"Path to same xml file that generated by above serializer");