Mengonversi objek menjadi string XML


89

Saya punya kelas bernama WebserviceTypesaya dapatkan dari alat xsd.exe dari file XSD.

Sekarang saya ingin deserialize instance WebServiceTypeobjek menjadi string. Bagaimana saya bisa melakukan ini?

The MethodCheckTypeobjek memiliki sebagai params sebuah WebServiceTypearray yang.

Percobaan pertama saya seperti saya membuat serialnya: dengan a XmlSerializerdan a StringWriter(sementara serialisasi saya menggunakan a StringReader).

Ini adalah metode di mana saya membuat serial WebServiceTypeobjek:

XmlSerializer serializer = new XmlSerializer(typeof(MethodCheckType));
        MethodCheckType output = null;
        StringReader reader = null;

        // catch global exception, logg it and throw it
        try
        {
            reader = new StringReader(path);
            output = (MethodCheckType)serializer.Deserialize(reader);
        }
        catch (Exception)
        {
            throw;
        }
        finally
        {
            reader.Dispose();
        }

        return output.WebService;

Edit:

Mungkin saya bisa mengatakannya dengan kata-kata yang berbeda: Saya telah mendapat contoh dari MethodCheckTypeobjek ini dan di sisi lain saya telah mendapatkan dokumen XML dari mana saya membuat serial objek ini. Sekarang saya ingin mengubah contoh ini menjadi dokumen XML dalam bentuk string. Setelah ini saya harus membuktikan apakah kedua string (dokumen XML) sama. Ini harus saya lakukan, karena saya membuat tes unit dari metode pertama di mana saya membaca dokumen XML menjadi StringReaderdan menserialisasinya menjadi MethodCheckTypeobjek.


2
Kesalahan apa yang Anda dapatkan? Dan Anda mungkin bingung dengan istilah: serialisasi (dalam dunia XML) adalah mengubah dari sebuah objek menjadi XML ; deserialization mengubah dari XML menjadi sebuah objek . Apakah Anda ingin deserialisasi objek dari string XML?
carlosfigueira

Jawaban:


191

Berikut adalah metode konversi untuk kedua cara tersebut. this = instance dari kelas Anda

public string ToXML()
    {
        using(var stringwriter = new System.IO.StringWriter())
        { 
            var serializer = new XmlSerializer(this.GetType());
            serializer.Serialize(stringwriter, this);
            return stringwriter.ToString();
        }
    }

 public static YourClass LoadFromXMLString(string xmlText)
    {
        using(var stringReader = new System.IO.StringReader(xmlText))
        {
            var serializer = new XmlSerializer(typeof(YourClass ));
            return serializer.Deserialize(stringReader) as YourClass ;
        }
    }

14
Anda harus menggunakan usingpola atau Disposemetode panggilan untuk melepaskan sumber daya yang benar.
Ivan Kochurkin

Anda harus yakin untuk semua versi CLR daripada kode yang tidak dikelola tidak digunakan.
AlphaOmega

3
Mengapa? Karena Anda harus Buang semua yang membutuhkan sumber daya intensif (tidak terkelola dan terkelola ). Hanya karena pemulung akan membersihkan untuk Anda (pada akhirnya) tidak berarti Anda harus membuat pekerjaan itu terlalu sulit. Bersihkan seiring Anda melanjutkan dan kode Anda akan lebih efisien. Info lebih lanjut tentang mengapa membuang eksplisit adalah ide yang bagus di sini
Liam

1
hanya untuk kejelasan. kalian berbicara tentang membuang StringWriter dan StringReader (karena XmlSerializer tidak memiliki metode Dispose)
symbiont

bukankah akhir dari fungsi melepaskan sumber daya seefisien using? @Tokopedia
Mark Entingh

77

Saya menyadari ini adalah posting yang sangat lama, tetapi setelah melihat tanggapan LB, saya berpikir tentang bagaimana saya dapat meningkatkan jawaban yang diterima dan menjadikannya umum untuk aplikasi saya sendiri. Inilah yang saya dapatkan:

public static string Serialize<T>(T dataToSerialize)
{
    try
    {
        var stringwriter = new System.IO.StringWriter();
        var serializer = new XmlSerializer(typeof(T));
        serializer.Serialize(stringwriter, dataToSerialize);
        return stringwriter.ToString();
    }
    catch
    {
        throw;
    }
}

public static T Deserialize<T>(string xmlText)
{
    try
    {
        var stringReader = new System.IO.StringReader(xmlText);
        var serializer = new XmlSerializer(typeof(T));
        return (T)serializer.Deserialize(stringReader);
    }
    catch
    {
        throw;
    }
}

Metode ini sekarang dapat ditempatkan di kelas pembantu statis, yang berarti tidak ada duplikasi kode untuk setiap kelas yang perlu diserialkan.


10
Pada metode "Serialize", gunakan dataToSerialize.GetType () sebagai ganti typeof (T). Pada pandangan pertama ini tampaknya aman untuk menggunakan T sebagai tipe, tetapi jika objek "dataToSerialize" telah dilemparkan ke tipe induk (ChildClass dilemparkan ke BaseClass) itu akan memunculkan kesalahan. Dan periksa dulu untuk null.
Paul Paskah

1
Apa gunanya menangkap hanya untuk melempar ulang tanpa melakukan hal lain?
hancurkan

Pertanyaan bagus; Saya tidak mencoba mengembangkan gambaran lengkap di sini hanya kerangka fungsionalitas, dan saya pasti tidak ingin memberikan contoh yang menelan pengecualian. Tampak seperti alternatif umum yang bagus pada saat itu. Jangan ragu untuk menyarankan perbaikan!
William Smith

Solusi bagus yang dapat digunakan kembali.
Nitesh Saxena

21
    public static string Serialize(object dataToSerialize)
    {
        if(dataToSerialize==null) return null;

        using (StringWriter stringwriter = new System.IO.StringWriter())
        {
            var serializer = new XmlSerializer(dataToSerialize.GetType());
            serializer.Serialize(stringwriter, dataToSerialize);
            return stringwriter.ToString();
        }
    }

    public static T Deserialize<T>(string xmlText)
    {
        if(String.IsNullOrWhiteSpace(xmlText)) return default(T);

        using (StringReader stringReader = new System.IO.StringReader(xmlText))
        {
            var serializer = new XmlSerializer(typeof(T));
            return (T)serializer.Deserialize(stringReader);
        }
    }

1
Serialize memang membutuhkan obat generik. Objek sudah cukup. if (dataToSerialize == null) return null; ... var serializer = new XmlSerializer (dataToSerialize.GetType ()); ...
AlphaOmega

0

Ini adalah solusi saya, untuk objek daftar apa pun Anda dapat menggunakan kode ini untuk dikonversi ke tata letak xml. KeyFather adalah tag utama Anda dan KeySon adalah tempat memulai Forech Anda.

public string BuildXml<T>(ICollection<T> anyObject, string keyFather, string keySon)
    {
        var settings = new XmlWriterSettings
        {
            Indent = true
        };
        PropertyDescriptorCollection props = TypeDescriptor.GetProperties(typeof(T));
        StringBuilder builder = new StringBuilder();
        using (XmlWriter writer = XmlWriter.Create(builder, settings))
        {
            writer.WriteStartDocument();
            writer.WriteStartElement(keyFather);
            foreach (var objeto in anyObject)
            {
                writer.WriteStartElement(keySon);
                foreach (PropertyDescriptor item in props)
                {
                    writer.WriteStartElement(item.DisplayName);
                    writer.WriteString(props[item.DisplayName].GetValue(objeto).ToString());
                    writer.WriteEndElement();
                }
                writer.WriteEndElement();
            }
            writer.WriteFullEndElement();
            writer.WriteEndDocument();
            writer.Flush();
            return builder.ToString();
        }
    }

0
 public static class XMLHelper
    {
        /// <summary>
        /// Usage: var xmlString = XMLHelper.Serialize<MyObject>(value);
        /// </summary>
        /// <typeparam name="T">Kiểu dữ liệu</typeparam>
        /// <param name="value">giá trị</param>
        /// <param name="omitXmlDeclaration">bỏ qua declare</param>
        /// <param name="removeEncodingDeclaration">xóa encode declare</param>
        /// <returns>xml string</returns>
        public static string Serialize<T>(T value, bool omitXmlDeclaration = false, bool omitEncodingDeclaration = true)
        {
            if (value == null)
            {
                return string.Empty;
            }
            try
            {
                var xmlWriterSettings = new XmlWriterSettings
                {
                    Indent = true,
                    OmitXmlDeclaration = omitXmlDeclaration, //true: remove <?xml version="1.0" encoding="utf-8"?>
                    Encoding = Encoding.UTF8,
                    NewLineChars = "", // remove \r\n
                };

                var xmlserializer = new XmlSerializer(typeof(T));

                using (var memoryStream = new MemoryStream())
                {
                    using (var xmlWriter = XmlWriter.Create(memoryStream, xmlWriterSettings))
                    {
                        xmlserializer.Serialize(xmlWriter, value);
                        //return stringWriter.ToString();
                    }

                    memoryStream.Position = 0;
                    using (var sr = new StreamReader(memoryStream))
                    {
                        var pureResult = sr.ReadToEnd();
                        var resultAfterOmitEncoding = ReplaceFirst(pureResult, " encoding=\"utf-8\"", "");
                        if (omitEncodingDeclaration)
                            return resultAfterOmitEncoding;
                        return pureResult;
                    }
                }
            }
            catch (Exception ex)
            {
                throw new Exception("XMLSerialize error: ", ex);
            }
        }

        private static string ReplaceFirst(string text, string search, string replace)
        {
            int pos = text.IndexOf(search);

            if (pos < 0)
            {
                return text;
            }

            return text.Substring(0, pos) + replace + text.Substring(pos + search.Length);
        }
    }
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.