将对象转换为 XML 字符串
Posted
技术标签:
【中文标题】将对象转换为 XML 字符串【英文标题】:Convert an object to an XML string 【发布时间】:2012-07-11 22:46:46 【问题描述】:我有一个名为 WebserviceType
的类,我是从 XSD 文件中的 xsd.exe 工具获得的。
现在我想将WebServiceType
对象的实例反序列化为字符串。
我该怎么做?
MethodCheckType
对象有一个 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
对象。
【问题讨论】:
你得到什么错误?您可能会混淆这些术语:序列化(在 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 字符串的主要内容,如果未能解决你的问题,请参考以下文章
Android:将 Json 对象转换为 Strings.xml