2010-11-08 113 views
187

我有一个继承的C#类。我已经成功“构建”了这个对象。但我需要将对象序列化为XML。有没有简单的方法来做到这一点?将对象序列化为XML

它看起来像类已设置了序列化,但我不知道如何让XML表示。我的类定义是这样的:

[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")] 
[System.SerializableAttribute()] 
[System.Diagnostics.DebuggerStepThroughAttribute()] 
[System.ComponentModel.DesignerCategoryAttribute("code")] 
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.domain.com/test")] 
[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.domain.com/test", IsNullable = false)] 
public partial class MyObject 
{ 
    ... 
} 

这是我想我能做到,但它不工作:

MyObject o = new MyObject(); 
// Set o properties 
string xml = o.ToString(); 

我如何获得此对象的XML表示?

+0

我开发了一个简单的库做实现这一点:https://github.com/aishwaryashiva/SaveXML – 2015-08-28 14:03:51

+0

另请参阅:XML序列化和反序列化在CodeProject](http://www.codeproject.com/Articles/487571/XML-Serializ通货膨胀-和反序列化-部分) – 2014-09-14 14:59:19

回答

338

你必须使用XmlSerializer的用于XML序列化。以下是一个示例代码片段。

XmlSerializer xsSubmit = new XmlSerializer(typeof(MyObject)); 
var subReq = new MyObject(); 
var xml = ""; 

using(var sww = new StringWriter()) 
{ 
    using(XmlWriter writer = XmlWriter.Create(sww)) 
    { 
     xsSubmit.Serialize(writer, subReq); 
     xml = sww.ToString(); // Your XML 
    } 
} 
+9

似乎没有行'XmlWriter的作家= XmlWriter.Create(SWW),以很好地工作;'' – 2014-06-27 10:52:21

+105

人using'使用'using's!处理这些对象! – Liam 2014-09-11 16:25:25

+8

要序列化的对象格式化:''XmlTextWriter writer = new XmlTextWriter(sww){Formatting = Formatting.Inpression};''而不是'XmlWriter writer = XmlWriter.Create(sww);' – 2015-06-21 15:22:33

13

序列化一个对象,这样做:

using (StreamWriter myWriter = new StreamWriter(path, false)) 
{ 
    XmlSerializer mySerializer = new XmlSerializer(typeof(your_object_type)); 
    mySerializer.Serialize(myWriter, objectToSerialize); 
} 

还记得那对XmlSerializer的工作,你需要一个参数的构造函数。

+1

这让我疯狂。我无法弄清楚它为什么总是空白。然后在阅读你的答案后意识到我没有没有参数的构造函数。谢谢。 – Andy 2017-01-23 19:45:31

6

它比调用类的ToString方法更复杂一点,但不多。

这里有一个简单的插入式功能,您可以使用序列化的任何类型的对象。它返回一个包含序列化XML内容的字符串:

public string SerializeObject(object obj) 
{ 
    System.Xml.XmlDocument xmlDoc = new System.Xml.XmlDocument(); 
    System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(obj.GetType()); 
    using (System.IO.MemoryStream ms = new System.IO.MemoryStream()) { 
     serializer.Serialize(ms, obj); 
     ms.Position = 0; 
     xmlDoc.Load(ms); 
     return xmlDoc.InnerXml; 
    } 
} 
27

您可以使用下面的函数从任何对象获取序列化的XML。

public static bool Serialize<T>(T value, ref string serializeXml) 
{ 
    if (value == null) 
    { 
     return false; 
    } 
    try 
    { 
     XmlSerializer xmlserializer = new XmlSerializer(typeof(T)); 
     StringWriter stringWriter = new StringWriter(); 
     XmlWriter writer = XmlWriter.Create(stringWriter); 

     xmlserializer.Serialize(writer, value); 

     serializeXml = stringWriter.ToString(); 

     writer.Close(); 
     return true; 
    } 
    catch (Exception ex) 
    { 
     return false; 
    } 
} 

您可以从客户端调用此函数。

28

下面的函数可以被复制到任何对象添加一个XML使用System.Xml命名空间保存功能。

/// <summary> 
/// Saves to an xml file 
/// </summary> 
/// <param name="FileName">File path of the new xml file</param> 
public void Save(string FileName) 
{ 
    using (var writer = new System.IO.StreamWriter(FileName)) 
    { 
     var serializer = new XmlSerializer(this.GetType()); 
     serializer.Serialize(writer, this); 
     writer.Flush(); 
    } 
} 

要从保存的文件创建对象,请添加以下函数,并用要创建的对象类型替换[ObjectType]。

/// <summary> 
/// Load an object from an xml file 
/// </summary> 
/// <param name="FileName">Xml file name</param> 
/// <returns>The object created from the xml file</returns> 
public static [ObjectType] Load(string FileName) 
{ 
    using (var stream = System.IO.File.OpenRead(FileName)) 
    { 
     var serializer = new XmlSerializer(typeof([ObjectType])); 
     return serializer.Deserialize(stream) as [ObjectType]; 
    } 
} 
+0

'writer.Flush()'在'using'块中是多余的'''''''''Dispose()'方法将为您刷新。 – bavaza 2015-03-13 10:38:19

+1

我的经验发现并非如此。对于更大的数据,using语句将在清除缓冲区之前处理该流。我100%建议明确调用刷新。 – 2015-03-14 05:27:26

+1

writer.Flush()不是多余的,它必须在那里。如果没有刷新,可能会发生部分数据仍在StreamWriter缓冲区中,并且文件被丢弃并且某些数据丢失。 – qub1n 2015-11-14 20:49:46

79

我修改了mine来返回一个字符串,而不是像下面那样使用ref变量。

public static string Serialize<T>(this T value) 
{ 
    if (value == null) 
    { 
     return string.Empty; 
    } 
    try 
    { 
     var xmlserializer = new XmlSerializer(typeof(T)); 
     var stringWriter = new StringWriter(); 
     using (var writer = XmlWriter.Create(stringWriter)) 
     { 
      xmlserializer.Serialize(writer, value); 
      return stringWriter.ToString(); 
     } 
    } 
    catch (Exception ex) 
    { 
     throw new Exception("An error occurred", ex); 
    } 
} 

它的用法是这样的:

var xmlString = obj.Serialize(); 
+7

非常好的解决方案,我喜欢你作为扩展方法实现这个方法 – Spyros 2013-08-30 11:38:01

+34

我在这里建议的一件事:删除try ... catch块。它没有给你带来任何好处,只是模糊了正在抛出的错误。 – jammycakes 2014-10-20 10:50:20

+1

难道你不需要使用串口打字机吗?例如:使用(var stringWriter = new StringWriter()) – 2015-08-13 00:57:20

23

扩展类:

using System.IO; 
using System.Xml; 
using System.Xml.Serialization; 

namespace MyProj.Extensions 
{ 
    public static class XmlExtension 
    { 
     public static string Serialize<T>(this T value) 
     { 
      if (value == null) return string.Empty; 

      var xmlSerializer = new XmlSerializer(typeof(T)); 

      using (var stringWriter = new StringWriter()) 
      { 
       using (var xmlWriter = XmlWriter.Create(stringWriter,new XmlWriterSettings{Indent = true})) 
       { 
        xmlSerializer.Serialize(xmlWriter, value); 
        return stringWriter.ToString(); 
       }  
      } 
     } 
    } 
} 

用法:

Foo foo = new Foo{MyProperty="I have been serialized"}; 

string xml = foo.Serialize(); 

只是引用该命名空间牵着你的扩展方法在你想要的文件o使用它,它会工作(在我的例子中,它将是:using MyProj.Extensions;

请注意,如果您想使扩展方法仅针对特定类(例如,Foo),您可以将T参数在扩展方法中,例如。

public static string Serialize(this Foo value){...}

+0

我试过这段代码,因为它看起来是最干净的,但在最后一行它没有提供“Serialize()”方法。我错过了什么? – ditto1977 2014-12-26 15:29:56

+0

@ user312305我最真诚的道歉,我发布了错误的版本。请看我编辑的答案,不需要继承,它只适用于所有对象! – 2014-12-26 16:29:21

+0

非常好,我的朋友!现在我只使用'XmlExtension.Serialize(foo);'一切都很好!非常感谢。 – ditto1977 2014-12-26 17:16:20

1

或者你可以将这个方法添加到您的对象:

public void Save(string filename) 
    { 
     var ser = new XmlSerializer(this.GetType()); 
     using (var stream = new FileStream(filename, FileMode.Create)) 
      ser.Serialize(stream, this); 
    } 
12

我将开始与本Gripka副本答案:

public void Save(string FileName) 
{ 
    using (var writer = new System.IO.StreamWriter(FileName)) 
    { 
     var serializer = new XmlSerializer(this.GetType()); 
     serializer.Serialize(writer, this); 
     writer.Flush(); 
    } 
} 

我这个代码之前使用。但现实表明,这个解决方案有点问题。通常,大多数程序员只是在载入时序列化保存和反序列化设置。这是一个乐观的情景。一旦序列化失败,由于某种原因,文件被部分写入,XML文件不完整,并且是无效的。因此,XML反序列化不起作用,您的应用程序可能会在开始时崩溃。如果文件不是很大,我建议首先将对象序列化为MemoryStream,然后将流写入文件。如果有一些复杂的自定义序列化,这种情况尤其重要。你永远不能测试所有的情况。

public void Save(string fileName) 
{ 
    //first serialize the object to memory stream, 
    //in case of exception, the original file is not corrupted 
    using (MemoryStream ms = new MemoryStream()) 
    { 
     var writer = new System.IO.StreamWriter(ms);  
     var serializer = new XmlSerializer(this.GetType()); 
     serializer.Serialize(writer, this); 
     writer.Flush(); 

     //if the serialization succeed, rewrite the file. 
     File.WriteAllBytes(fileName, ms.ToArray()); 
    } 
} 

在现实世界中的场景应该与损坏的序列号文件数的反序列化,它的某个时候发生。 Ben Gripka提供的加载功能很好。

public static [ObjectType] Load(string fileName) 
{ 
    using (var stream = System.IO.File.OpenRead(fileName)) 
    { 
     var serializer = new XmlSerializer(typeof([ObjectType])); 
     return serializer.Deserialize(stream) as [ObjectType];   
    }  
} 

它可以被一些恢复场景包装。它适用于设置文件或其他可以在出现问题时删除的文件。

public static [ObjectType] LoadWithRecovery(string fileName) 
{ 
    try 
    { 
     return Load(fileName); 
    } 
    catch(Excetion) 
    { 
     File.Delete(fileName); //delete corrupted settings file 
     return GetFactorySettings(); 
    } 
} 
2
string FilePath = ConfigurationReader.FileLocation; //Getting path value from web.config    
    XmlSerializer serializer = new XmlSerializer(typeof(Devices)); //typeof(object) 
      MemoryStream memStream = new MemoryStream(); 
      serializer.Serialize(memStream, lstDevices);//lstdevices : I take result as a list. 
      FileStream file = new FileStream(folderName + "\\Data.xml", FileMode.Create, FileAccess.ReadWrite); //foldername:Specify the path to store the xml file 
      memStream.WriteTo(file); 
      file.Close(); 

您可以创建并存储结果作为在所需位置xml文件。

1

我的工作代码。返回utf8 xml启用空名称空间。

// override StringWriter 
public class Utf8StringWriter : StringWriter 
{ 
    public override Encoding Encoding => Encoding.UTF8; 
} 

private string GenerateXmlResponse(Object obj) 
{  
    Type t = obj.GetType(); 

    var xml = ""; 

    using (StringWriter sww = new Utf8StringWriter()) 
    { 
     using (XmlWriter writer = XmlWriter.Create(sww)) 
     { 
      var ns = new XmlSerializerNamespaces(); 
      // add empty namespace 
      ns.Add("", ""); 
      XmlSerializer xsSubmit = new XmlSerializer(t); 
      xsSubmit.Serialize(writer, obj, ns); 
      xml = sww.ToString(); // Your XML 
     } 
    } 
    return xml; 
} 

示例返回响应Yandex的API金说Aviso网址:

<?xml version="1.0" encoding="utf-8"?><paymentAvisoResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" performedDatetime="2017-09-01T16:22:08.9747654+07:00" code="0" shopId="54321" invoiceId="12345" orderSumAmount="10643" /> 
0

这是一个基本的代码,这将有助于序列化的C#对象转换为XML:

using System; 

public class clsPerson 
{ 
    public string FirstName; 
    public string MI; 
    public string LastName; 
} 

class class1 
{ 
    static void Main(string[] args) 
    { 
     clsPerson p=new clsPerson(); 
     p.FirstName = "Jeff"; 
     p.MI = "A"; 
     p.LastName = "Price"; 
     System.Xml.Serialization.XmlSerializer x = new System.Xml.Serialization.XmlSerializer(p.GetType()); 
     x.Serialize(Console.Out, p); 
     Console.WriteLine(); 
     Console.ReadLine(); 
    } 
}