如何将不同对象与DataSet序列化到同一XML并实现追加写入?
问题
需要用单个XML文件存储5个不同类型的类对象和1个DataSet的序列化值,要求每个对象(包括DataSet的内容)都有独立的根元素。目前已通过类上的XmlRoot特性实现对象序列化,但不知道如何让XmlSerializer或XmlWriter追加写入现有XML(不存在则创建)而非覆盖。
当前序列化类的代码:
var sts = new XmlWriterSettings() { Indent = true, OmitXmlDeclaration = true, }; var xs = new XmlSerializer(typeof(MyClassName)); var filename = "whatever.xml"; XmlWriter w = XmlWriter.Create(filename, sts); xs.Serialize(w, objReference); w.Close();
写入DataSet的代码:
var filename = "whatever.xml"; myDataSet.myTable.WriteXml(filename, XmlWriteMode.IgnoreSchema);
解决方案
首先明确:标准XML文档仅允许存在一个顶级根元素,因此不能直接追加多个独立根节点,必须先创建一个统一的根容器(例如<RootContainer>),所有对象和DataSet的序列化内容都作为该容器的子节点存在。
1. 初始化XML文件(首次创建)
如果目标文件不存在,先创建包含根容器的基础XML结构:
var filename = "whatever.xml"; if (!File.Exists(filename)) { using (var writer = XmlWriter.Create(filename, new XmlWriterSettings { Indent = true })) { writer.WriteStartDocument(); writer.WriteStartElement("RootContainer"); // 定义统一根容器 writer.WriteEndElement(); writer.WriteEndDocument(); } }
2. 追加序列化的类对象
通过加载现有XML文档,将序列化后的对象节点插入根容器:
public void AppendObjectToXml<T>(T obj, string filename) where T : class { var mainDoc = new XmlDocument(); mainDoc.Load(filename); var rootContainer = mainDoc.DocumentElement; // 获取根容器节点 // 将对象序列化为XmlNode var serializer = new XmlSerializer(typeof(T)); using (var ms = new MemoryStream()) { serializer.Serialize(ms, obj); ms.Position = 0; var objDoc = new XmlDocument(); objDoc.Load(ms); // 将对象节点导入主文档并追加到根容器 var importedNode = mainDoc.ImportNode(objDoc.DocumentElement, true); rootContainer.AppendChild(importedNode); } mainDoc.Save(filename); }
调用示例:
var myObj = new MyClassName(); AppendObjectToXml(myObj, "whatever.xml");
3. 追加DataSet的内容
采用相同思路,将DataSet的XML内容作为子节点插入根容器:
public void AppendDataSetToXml(DataSet dataSet, string filename) { var mainDoc = new XmlDocument(); mainDoc.Load(filename); var rootContainer = mainDoc.DocumentElement; // 将DataSet内容序列化为XmlNode using (var ms = new MemoryStream()) { dataSet.myTable.WriteXml(ms, XmlWriteMode.IgnoreSchema); ms.Position = 0; var dsDoc = new XmlDocument(); dsDoc.Load(ms); // 导入DataSet节点并追加到根容器 var importedNode = mainDoc.ImportNode(dsDoc.DocumentElement, true); rootContainer.AppendChild(importedNode); } mainDoc.Save(filename); }
调用示例:
AppendDataSetToXml(myDataSet, "whatever.xml");
关键注意事项
- 每个要序列化的类需保留
XmlRoot特性,确保生成的节点符合预期结构 - 操作XML时建议使用
using语句,确保流和文档对象正确释放,避免文件锁问题 - 每次追加操作都需重新加载整个XML文档,防止并发写入冲突
内容的提问来源于stack exchange,提问作者totalZero
相关产品推荐
相关产品推荐

