Перетворити об’єкт на рядок XML


88

У мене є клас, який 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 ; десеріалізація - це перетворення з XML в об'єкт . Ви хочете десериалізувати об'єкт із рядка XML?
carlosfigueira

Відповіді:


188

Ось спосіб перетворення в обидва шляхи. 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 ;
        }
    }

13
Для правильного звільнення ресурсів слід використовувати usingшаблон або Disposeметод виклику .
Іван Кочуркін

Ви повинні бути впевнені, що для всіх версій CLR не використовується керований код.
AlphaOmega

3
Чому? Тому що ви повинні розпоряджатися всім ресурсоємним (некерованим та керованим ). Тільки тому, що збирач сміття за вас прибере (врешті-решт), не означає, що вам слід надмірно ускладнити цю роботу. Прибирайте, як ви рухаєтесь, і ваш код буде більш ефективним. Більше інформації про те, чому явне розпорядження - це гарна ідея, тут
Ліам

1
просто для наочності. ви, хлопці, говорите про утилізацію StringWriter та StringReader (оскільки XmlSerializer не має методу Dispose)
симбіонт

чи кінець функції не вивільняє ресурси так само ефективно, як using? @KvanTTT?
Mark Entingh

77

Я усвідомлюю, що це дуже стара публікація, але, подивившись відповідь 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
У методі "Серіалізація" використовуйте dataToSerialize.GetType () замість typeof (T). На перший погляд здається безпечним використовувати T як тип, але якщо об'єкт "dataToSerialize" був переданий батьківському типу (ChildClass приведений до BaseClass), це видасть помилку. І спершу перевірте його на нуль.
Павло Пасха

1
Який сенс ловити, щоб просто перекинути, не роблячи нічого іншого?
розчавити

Чудове питання; Я не намагався скласти тут повну картину, а лише рамки для функціональних можливостей, і я точно не хотів наводити приклад, який ковтає виняток. На той час це здавалося хорошою загальною альтернативою. Не соромтеся пропонувати вдосконалення!
Вільям Сміт

Хороше багаторазове рішення.
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
Серіалізація дійсно потребує дженериків. Об'єкта досить. if (dataToSerialize == null) повертає null; ... var serializer = new 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);
        }
    }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.