C#中使用System.Xml.Serialization处理含未知元素的XML序列化/反序列化
保留XML未知元素并修改指定节点(System.Xml.Serialization实现)
问题场景
假设你有如下XML结构:
<MyObject> <Files> <File>1</File> <File>2</File> </Files> <Directories> <File>3</File> </Directories> </MyObject>
针对已知结构,你可以通过定义对应模型类反序列化,修改Files集合后再序列化:
class MyObject { public List<File> Files { get; set; } public List<File> Directories { get; set; } } class File { [XmlText] public string Value { get; set; } }
调用Files.Add(new File { Value = "4" })后序列化,就能正常更新XML内容。
但如果XML中存在未知元素(如下方的SomeAttrib1、SomeAttrib2),你无法提前预知这些元素的存在,直接用原有模型序列化会丢失未知内容:
<MyObject> <Files> <File>1</File> <File>2</File> </Files> <Directories> <File>3</File> </Directories> <SomeAttrib1>...</SomeAttrib1> <SomeAttrib2>...</SomeAttrib2> </MyObject>
解决方案
利用System.Xml.Serialization提供的未知元素/属性捕获机制,在模型类中添加对应特性来保存未知内容,确保序列化时完整保留。
1. 调整模型类
在MyObject中添加[XmlAnyElement]和[XmlAnyAttribute]标记的属性,用于存储未知元素和属性:
using System.Xml.Serialization; using System.Xml; [XmlRoot("MyObject")] class MyObject { // 已知的Files节点 public List<File> Files { get; set; } // 已知的Directories节点 public List<File> Directories { get; set; } // 捕获所有未知XML元素 [XmlAnyElement] public XmlElement[] UnknownElements { get; set; } // 捕获所有未知XML属性(不需要可省略) [XmlAnyAttribute] public XmlAttribute[] UnknownAttributes { get; set; } } class File { [XmlText] public string Value { get; set; } }
2. 反序列化并修改指定节点
正常反序列化XML到MyObject实例,修改Files或Directories集合后重新序列化,未知元素会被完整保留:
// 反序列化示例 XmlSerializer serializer = new XmlSerializer(typeof(MyObject)); using (FileStream fs = new FileStream("input.xml", FileMode.Open)) { MyObject obj = (MyObject)serializer.Deserialize(fs); // 修改Files节点,添加新文件 obj.Files.Add(new File { Value = "4" }); // 序列化回XML,保留所有未知元素 using (FileStream outputFs = new FileStream("output.xml", FileMode.Create)) { serializer.Serialize(outputFs, obj); } }
关键说明
[XmlAnyElement]会将所有未在模型中定义的XML元素序列化为XmlElement数组,序列化时会原样输出这些元素[XmlAnyAttribute]用于捕获未知的XML属性,不需要可以省略- 模型类的属性必须是公共可读写属性(带
get; set;),否则XmlSerializer无法正常处理
内容的提问来源于stack exchange,提问作者pawelek91
相关产品推荐
相关产品推荐

