【问题标题】:Convert an object to an XML string将对象转换为 XML 字符串
【发布时间】: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字符串反序列化一个对象吗?

标签: c# xml serialization


【解决方案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();
            }
        }
    

    【讨论】:

      猜你喜欢
      • 2011-03-12
      • 1970-01-01
      • 2013-06-20
      • 2018-11-27
      • 2015-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多