Перетворити об’єкт на рядок 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.