Преобразование объекта в строку XML


89

У меня есть класс с именем, который WebserviceTypeя получил от инструмента xsd.exe из файла XSD.

Теперь я хочу десериализовать экземпляр WebServiceTypeобъекта в строку. Как я могу это сделать?

MethodCheckTypeОбъект имеет , как Params в WebServiceTypeмассив.

Моя первая попытка была как будто я сериализовал его: с помощью XmlSerializerи StringWriter(при сериализации я использовал 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-документ в StringReaderи сериализую его в MethodCheckTypeобъект.


2
Какая у вас ошибка? И вы можете запутать термины: сериализация (в мире XML) - это преобразование объекта в XML ; десериализация - это преобразование из XML в объект . Вы хотите десериализовать объект из строки XML?
carlosfigueira

Ответы:


190

Вот метод преобразования для обоих способов. 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метод вызова для правильного высвобождения ресурсов.
Иван Кочуркин

Вы должны быть уверены, что для всех версий CLR не используется неуправляемый код.
AlphaOmega

3
Зачем? Потому что вы должны утилизировать все, что является ресурсоемким (неуправляемым и управляемым ). Просто потому, что сборщик мусора очистит за вас (в конце концов), это не означает, что вы должны сделать его работу чрезмерно сложной. Убирайте по мере продвижения, и ваш код станет более эффективным. Подробнее о том, почему явная утилизация - хорошая идея, можно здесь
Лиам,

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

разве конец функции не высвобождает ресурсы так же эффективно, как using? @KvanTTT?
Марк Энтинг,

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), это вызовет ошибку. И, конечно, сначала проверьте его на null.
Пол Истер

1
Какой смысл ловить, чтобы просто перебросить, ничего не делая?
Crush

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

Хорошее многоразовое решение.
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
Для сериализации нужны дженерики. Объекта достаточно. если (dataToSerialize == null) return 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.