Chuyển đổi một đối tượng thành một chuỗi XML


88

Tôi có một lớp có tên là WebserviceTypetôi nhận được từ công cụ xsd.exe từ tệp XSD.

Bây giờ tôi muốn giải mã hóa một thể hiện của một WebServiceTypeđối tượng thành một chuỗi. Tôi có thể làm cái này như thế nào?

Đối MethodCheckTypetượng có các tham số là một WebServiceTypemảng.

Lần thử đầu tiên của tôi giống như tôi đã tuần tự hóa nó: với a XmlSerializervà a StringWriter(trong khi tuần tự hóa tôi đã sử dụng a StringReader).

Đây là phương pháp mà tôi tuần tự hóa WebServiceTypeđối tượng:

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;

Biên tập:

Có lẽ tôi có thể nói nó bằng những từ khác: Tôi đã có một phiên bản của MethodCheckTypeđối tượng này, mặt khác tôi có tài liệu XML mà từ đó tôi đã tuần tự hóa đối tượng này. Bây giờ tôi muốn chuyển đổi trường hợp này thành một tài liệu XML dưới dạng một chuỗi. Sau đó, tôi phải chứng minh xem cả hai chuỗi (của tài liệu XML) có giống nhau hay không. Điều này tôi phải làm, bởi vì tôi thực hiện các bài kiểm tra đơn vị của phương pháp đầu tiên mà tôi đọc tài liệu XML thành một StringReadervà tuần tự hóa nó thành một MethodCheckTypeđối tượng.


2
lỗi gì bạn nhận được? Và bạn có thể nhầm lẫn với các thuật ngữ: tuần tự hóa (trong thế giới XML) là chuyển đổi từ một đối tượng thành XML ; deserialization là chuyển đổi từ XML thành một đối tượng . Bạn có muốn giải mã hóa một đối tượng từ một chuỗi XML không?
carlosfigueira

Câu trả lời:


188

Đây là phương pháp chuyển đổi cho cả hai cách. this = phiên bản của lớp bạn

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

13
Bạn nên sử dụng usingmẫu hoặc Disposephương thức gọi để giải phóng tài nguyên chính xác.
Ivan Kochurkin

Bạn phải chắc chắn rằng đối với tất cả các phiên bản CLR, mã không được quản lý không được sử dụng.
AlphaOmega

3
Tại sao? Vì bạn nên Vứt bỏ mọi thứ ngốn tài nguyên (không được quản lý và quản lý ). Chỉ cần người thu gom rác sẽ dọn dẹp cho bạn (cuối cùng) không có nghĩa là bạn nên làm cho công việc đó trở nên khó khăn quá mức. Dọn dẹp khi bạn thực hiện và mã của bạn sẽ hiệu quả hơn. Thông tin thêm về xử lý tại sao rõ ràng là một ý tưởng tốt ở đây
Liam

1
chỉ để rõ ràng. các bạn đang nói về việc loại bỏ StringWriter và StringReader (vì XmlSerializer không có phương pháp Dispose)
symbiont

không phải phần cuối của hàm giải phóng tài nguyên hiệu quả như usingvậy? @KvanTTT?
Mark Entingh

77

Tôi nhận ra đây là một bài đăng rất cũ, nhưng sau khi xem phản hồi của LB, tôi đã nghĩ về cách tôi có thể cải thiện câu trả lời được chấp nhận và làm cho nó chung chung cho ứng dụng của tôi. Đây là những gì tôi nghĩ ra:

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

Các phương thức này bây giờ có thể được đặt trong một lớp trợ giúp tĩnh, có nghĩa là không có sự trùng lặp mã cho mọi lớp cần được tuần tự hóa.


10
Trên phương thức "Serialize", sử dụng dataToSerialize.GetType () thay vì typeof (T). Thoạt nhìn, điều này có vẻ an toàn khi sử dụng T làm kiểu, nhưng nếu đối tượng "dataToSerialize" đã được chuyển thành kiểu mẹ (ChildClass truyền thành BaseClass) thì nó sẽ gây ra lỗi. Và tất nhiên, hãy kiểm tra nó xem có null không.
Paul Easter

1
Có ích gì khi bắt chỉ để ném lại mà không làm gì khác?
nghiền nát

Câu hỏi tuyệt vời; Tôi không cố gắng phát triển một bức tranh hoàn chỉnh ở đây chỉ là khung cho chức năng và tôi chắc chắn không muốn đưa ra một ví dụ nuốt chửng ngoại lệ. Có vẻ như một giải pháp thay thế tốt, chung chung vào thời điểm đó. Hãy đề xuất những cải tiến!
William Smith

Giải pháp tái sử dụng tốt.
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 không cần generic. Đối tượng là đủ. if (dataToSerialize == null) trả về null; ... var serializer = new XmlSerializer (dataToSerialize.GetType ()); ...
AlphaOmega

0

Đây là giải pháp của tôi, đối với bất kỳ đối tượng danh sách nào, bạn có thể sử dụng mã này để chuyển đổi sang bố cục xml. KeyFather là thẻ chính của bạn và KeySon là nơi bắt đầu Forech của bạn.

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);
        }
    }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.