แปลงวัตถุเป็นสตริง XML


92

ฉันมีคลาสชื่อWebserviceTypeฉันได้มาจากเครื่องมือ xsd.exe จากไฟล์ XSD

ตอนนี้ฉันต้องการยกเลิกการเชื่อมต่ออินสแตนซ์ของWebServiceTypeวัตถุเป็นสตริง ฉันจะทำเช่นนี้ได้อย่างไร?

MethodCheckTypeวัตถุได้เป็น params WebServiceTypeอาร์เรย์

การลองครั้งแรกของฉันเหมือนกับว่าฉันทำให้เป็นอนุกรม: ด้วย a XmlSerializerและ a StringWriter(ในขณะที่ทำให้เป็นอนุกรมฉันใช้ a StringReader)

นี่คือวิธีการที่ฉันทำให้WebServiceTypeวัตถุเป็นอนุกรม:

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;

แก้ไข:

บางทีฉันอาจจะพูดเป็นคำอื่น: ฉันมีอินสแตนซ์ของMethodCheckTypeวัตถุนี้ในทางกลับกันฉันได้รับเอกสาร XML ที่ฉันจัดลำดับวัตถุนี้ ตอนนี้ฉันต้องการแปลงอินสแตนซ์นี้เป็นเอกสาร XML ในรูปแบบของสตริง หลังจากนี้ฉันต้องพิสูจน์ว่าสตริงทั้งสอง (ของเอกสาร XML) เหมือนกันหรือไม่ สิ่งนี้ฉันต้องทำเพราะฉันทำการทดสอบหน่วยของวิธีแรกที่ฉันอ่านเอกสาร XML ลงใน a StringReaderและทำให้เป็นอนุกรมเป็นMethodCheckTypeวัตถุ


2
คุณได้รับข้อผิดพลาดอะไร และคุณอาจจะสับสนข้อกำหนด: อนุกรม (ในโลก XML) คือการแปลงจากวัตถุเข้าของ XML ; deserialization คือการแปลงจาก XML เป็นวัตถุ คุณต้องการ deserialize วัตถุจากสตริง XML หรือไม่?
carlosfigueira

คำตอบ:


195

นี่คือวิธีการแปลงสำหรับทั้งสองวิธี this = อินสแตนซ์ของชั้นเรียนของคุณ

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
คุณควรใช้usingรูปแบบหรือDisposeวิธีการเรียกเพื่อการปล่อยทรัพยากรที่ถูกต้อง
Ivan Kochurkin

คุณต้องแน่ใจว่าสำหรับ CLR ทุกเวอร์ชันที่ไม่ใช่โค้ดที่ไม่มีการจัดการ
AlphaOmega

3
ทำไม? เนื่องจากคุณควรกำจัดทุกสิ่งที่ใช้ทรัพยากรมาก (ไม่มีการจัดการและจัดการ ) เพียงเพราะคนเก็บขยะจะทำความสะอาดให้คุณ (ในที่สุด) ไม่ได้หมายความว่าคุณควรทำให้งานนี้ยากเกินควร ทำความสะอาดตามที่คุณดำเนินการและรหัสของคุณจะมีประสิทธิภาพมากขึ้น ข้อมูลเพิ่มเติมว่าเหตุใดการทิ้งอย่างชัดเจนจึงเป็นความคิดที่ดี
Liam

1
เพียงเพื่อความชัดเจน พวกคุณกำลังพูดถึงการกำจัด StringWriter และ StringReader (เนื่องจาก XmlSerializer ไม่มีเมธอด Dispose)
symbiont

ไม่ใช่การสิ้นสุดของฟังก์ชันรีลีสรีซอร์สอย่างมีประสิทธิภาพเช่นเดียวกับ usingหรือ @KvanTTT?
Mark Entingh

79

ฉันรู้ว่านี่เป็นโพสต์เก่ามาก แต่หลังจากดูคำตอบของ LB แล้วฉันก็คิดว่าจะปรับปรุงคำตอบที่ยอมรับได้อย่างไรและทำให้เป็นแบบทั่วไปสำหรับแอปพลิเคชันของฉันเอง นี่คือสิ่งที่ฉันคิดขึ้น:

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

ขณะนี้วิธีการเหล่านี้สามารถวางไว้ในคลาสตัวช่วยแบบคงที่ซึ่งหมายความว่าไม่มีการทำซ้ำรหัสกับทุกคลาสที่ต้องต่ออนุกรม


10
ในวิธี "Serialize" ใช้ dataToSerialize.GetType () แทน typeof (T) เมื่อมองแวบแรกดูเหมือนว่าปลอดภัยที่จะใช้ T เป็นประเภท แต่ถ้าออบเจ็กต์ "dataToSerialize" ถูกส่งไปยังประเภทหลัก (ChildClass cast to BaseClass) จะทำให้เกิดข้อผิดพลาด และตรวจสอบค่าว่างก่อนแน่นอน
Paul Easter

1
อะไรคือจุดสำคัญในการปลูกใหม่โดยไม่ต้องทำอะไรอีก?
ขยี้

คำถามที่ดี; ฉันไม่ได้พยายามพัฒนาภาพที่สมบูรณ์ที่นี่เพียงแค่กรอบสำหรับฟังก์ชันการทำงานและแน่นอนฉันไม่ต้องการยกตัวอย่างที่กลืนข้อยกเว้น ดูเหมือนจะเป็นทางเลือกที่ดีและทั่วไปในเวลานั้น อย่าลังเลที่จะแนะนำการปรับปรุง!
William Smith

โซลูชันที่สามารถนำกลับมาใช้ใหม่ได้ดี
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 ไม่จำเป็นต้องมีชื่อสามัญ Object ก็เพียงพอแล้ว ถ้า (dataToSerialize == null) คืนค่า null; ... var serializer = XmlSerializer ใหม่ (dataToSerialize.GetType ()); ...
AlphaOmega

0

นี่คือทางออกของฉันสำหรับวัตถุรายการใด ๆ ที่คุณสามารถใช้รหัสนี้เพื่อแปลงเป็นเลย์เอาต์ xml KeyFather คือแท็กหลักของคุณและ KeySon คือจุดเริ่มต้น Forech ของคุณ

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);
        }
    }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.