Przekonwertuj obiekt na ciąg XML


88

Mam klasę o nazwie, WebserviceTypektórą otrzymałem z narzędzia xsd.exe z pliku XSD.

Teraz chcę deserializować wystąpienie WebServiceTypeobiektu do ciągu. Jak mogę to zrobić?

MethodCheckTypePrzedmiot ma za params w WebServiceTypetablicy.

Moja pierwsza próba była taka, jakbym ją serializował: z a XmlSerializeri StringWriter(podczas serializacji użyłem a StringReader).

Oto metoda, w której serializuję WebServiceTypeobiekt:

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;

Edytować:

Może mógłbym to powiedzieć innymi słowami: mam instancję tego MethodCheckTypeobiektu, az drugiej strony mam dokument XML, z którego serializowałem ten obiekt. Teraz chcę przekonwertować to wystąpienie na dokument XML w postaci ciągu. Następnie muszę udowodnić, czy oba ciągi znaków (dokumentów XML) są takie same. Muszę to zrobić, ponieważ wykonuję testy jednostkowe pierwszej metody, w której wczytuję dokument XML do a StringReaderi serializuję go do MethodCheckTypeobiektu.


2
Jaki błąd otrzymujesz? I możesz mylić terminy: serializacja (w świecie XML) to konwertowanie z obiektu do XML ; deserializacja to konwertowanie z XML do obiektu . Czy chcesz deserializować obiekt z ciągu XML?
— carlosfigueira

Odpowiedzi:


189

Oto metoda konwersji dla obu sposobów. this = instancja Twojej klasy

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
W celu poprawnego zwalniania zasobów należy użyć usingwzorca lub Disposemetody wywołania .
— Ivan Kochurkin

Musisz mieć pewność, że dla wszystkich wersji CLR kod niezarządzany nie jest używany.
— AlphaOmega

3
Czemu? Ponieważ należy pozbyć się wszystkiego, co wymaga dużej ilości zasobów (niezarządzane i zarządzane ). Tylko dlatego, że śmieciarz posprząta za Ciebie (w końcu), nie oznacza, że ​​powinieneś utrudniać jego pracę. Porządkuj w miarę postępów, a Twój kod będzie bardziej wydajny. Więcej informacji na temat tego, dlaczego wyraźne pozbywanie się jest dobrym pomysłem tutaj
— Liam

1
tylko dla jasności. mówicie o pozbyciu się StringWriter i StringReader (ponieważ XmlSerializer nie ma metody Dispose)
— symbiont

czy koniec funkcji nie zwalnia zasobów tak wydajnie, jak using? @KvanTTT?
— Mark Entingh

77

Zdaję sobie sprawę, że to bardzo stary post, ale po przyjrzeniu się odpowiedzi LB pomyślałem, jak mogę ulepszyć zaakceptowaną odpowiedź i uczynić ją ogólną dla mojej własnej aplikacji. Oto, co wymyśliłem:

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

Te metody można teraz umieścić w statycznej klasie pomocniczej, co oznacza brak duplikowania kodu do każdej klasy wymagającej serializacji.


10
W metodzie „Serialize” użyj dataToSerialize.GetType () zamiast typeof (T). Na pierwszy rzut oka użycie T jako typu wydaje się bezpieczne, ale jeśli obiekt „dataToSerialize” został rzutowany na typ nadrzędny (rzutowanie ChildClass na BaseClass), zgłosi błąd. I oczywiście najpierw sprawdź, czy jest null.
— Wielkanoc Pawła

1
Jaki jest sens łapania tylko po to, by ponownie rzucić bez robienia czegokolwiek innego?
— zmiażdżyć

Świetne pytanie; Nie próbowałem tworzyć tutaj pełnego obrazu, tylko ramy dla funkcjonalności i zdecydowanie nie chciałem podawać przykładu, który połyka wyjątek. Wtedy wydawało się, że to dobra, ogólna alternatywa. Zapraszam do sugerowania ulepszeń!
— William Smith

Dobre rozwiązanie wielokrotnego użytku.
— 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 potrzebuje typów generycznych. Obiekt wystarczy. if (dataToSerialize == null) return null; ... var serializer = new XmlSerializer (dataToSerialize.GetType ()); ...
— AlphaOmega

0

To jest moje rozwiązanie, dla dowolnego obiektu listy możesz użyć tego kodu do konwersji do układu XML. KeyFather to Twój główny tag, a KeySon to miejsce, w którym zaczniesz 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);
        }
    }
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.