将对象转换为 XML 字符串

Posted

技术标签:

【中文标题】将对象转换为 XML 字符串【英文标题】:Convert an object to an XML string 【发布时间】:2012-07-11 22:46:46 【问题描述】:

我有一个名为 WebserviceType 的类,我是从 XSD 文件中的 xsd.exe 工具获得的。

现在我想将WebServiceType 对象的实例反序列化为字符串。 我该怎么做?

MethodCheckType 对象有一个 WebServiceType 数组作为参数。

我的第一次尝试就像我序列化它:使用XmlSerializerStringWriter(序列化时我使用了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 对象。

【问题讨论】:

你得到什么错误?您可能会混淆这些术语:序列化(在 XML 世界中)是将 从对象转换为 XML;反序列化是将从 XML 转换为对象。你想一个XML字符串反序列化一个对象吗? 【参考方案1】:

以下是两种方式的转换方法。 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 ;
        
    

【讨论】:

您应该使用using模式或调用Dispose方法来正确释放资源。 您必须确保所有 CLR 版本都没有使用非托管代码。 为什么?因为您应该处置所有资源密集型(非托管和托管)。仅仅因为垃圾收集器会(最终)为你清理并不意味着你应该让它的工作变得过分困难。随着您的进行清理,您的代码将更加有效。 More info on why explicit disposing is a good idea here 只是为了清楚起见。你们正在谈论处置 StringWriter 和 StringReader(因为 XmlSerializer 没有 Dispose 方法) 函数结束释放资源不是和using一样高效吗? @KvanTTT ?【参考方案2】:

我意识到这是一篇非常古老的帖子,但在查看了 L.B 的回复后,我想到了如何改进已接受的答案并使其适用于我自己的应用程序。这是我想出的:

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;
    

这些方法现在可以放在静态帮助类中,这意味着不需要对每个需要序列化的类重复代码。

【讨论】:

在“Serialize”方法上,使用 dataToSerialize.GetType() 而不是 typeof(T)。乍一看,使用 T 作为类型似乎是安全的,但如果“dataToSerialize”对象已被转换为父类型(ChildClass 转换为 BaseClass),则会引发错误。当然首先检查它是否为空。 不做任何其他事情就重新投掷有什么意义? 好问题;我并没有试图在这里开发一个完整的图片,只是功能的框架,我绝对不想给出一个吞下异常的例子。当时似乎是一个很好的通用替代方案。欢迎提出改进建议! 良好的可重用解决方案。【参考方案3】:
    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);
        
    

【讨论】:

序列化确实需要泛型。对象就够了。 if(dataToSerialize==null) 返回空值; ... var serializer = new XmlSerializer(dataToSerialize.GetType()); ...【参考方案4】:
 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);
        
    

【讨论】:

【参考方案5】:

这是我的解决方案,对于任何列表对象,您都可以使用此代码转换为 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();
        
    

【讨论】:

以上是关于将对象转换为 XML 字符串的主要内容,如果未能解决你的问题,请参考以下文章

将 XML 转换为动态 C# 对象

将 Java 对象转换为 XML 字符串

Android:将 Json 对象转换为 Strings.xml

将 XML 字符串 API 响应转换为键值对象 C#

如何将带有参数数组的字符串 xml 转换为 .NET Core 中的对象

如何使用c#将xml字符串转换为对象