XmlSerializer处理非格式化XML时跳过元素的代码调整咨询
紧凑格式XML下XmlSerializer跳过元素的解决办法
问题现象
当XML为紧凑格式时:
<ArrayOfColumn><Column><COLUMN_NAME>SomeName1</COLUMN_NAME></Column><Column><COLUMN_NAME>SomeName2</COLUMN_NAME></Column></ArrayOfColumn>
以下C#代码会跳过第二个Column元素(若有更多元素则每隔一个跳过):
using (var xmlReader = XmlReader.Create(fileStream)) { var serializer = new XmlSerializer(typeof(MyColumnClass), new XmlRootAttribute("Column")); var myColumnList = new List<MyColumnClass>(); while (xmlReader.ReadToFollowing("Column")) { myColumnList.Add((MyColumnClass)serializer.Deserialize(xmlReader)); } // 后续代码 }
而当XML为格式化(带缩进)格式时,代码运行完全正常:
<ArrayOfColumn> <Column> <COLUMN_NAME>SomeName1</COLUMN_NAME> </Column> <Column> <COLUMN_NAME>SomeName2</COLUMN_NAME> </Column> </ArrayOfColumn>
问题原因
问题出在XmlReader.ReadToFollowing和XmlSerializer.Deserialize的配合逻辑上:
- 调用
ReadToFollowing("Column")找到目标元素后,Deserialize会读取整个Column元素(包括结束标签),此时XmlReader的位置停在</Column>之后。 - 紧凑格式XML中,下一个
<Column>紧跟在</Column>之后,ReadToFollowing会从当前位置扫描,阅读器会误判节点边界,导致跳过紧邻的<Column>元素。 - 格式化XML的换行和缩进让阅读器能正确识别节点边界,因此不会出现跳过问题。
解决办法
方法一:定义集合根类直接反序列化(推荐)
定义对应ArrayOfColumn的类,直接反序列化整个XML结构,无需手动遍历:
// 定义集合根类 [XmlRoot("ArrayOfColumn")] public class ArrayOfColumn { [XmlElement("Column")] public List<MyColumnClass> Columns { get; set; } = new List<MyColumnClass>(); } // 读取代码 using (var xmlReader = XmlReader.Create(fileStream)) { var serializer = new XmlSerializer(typeof(ArrayOfColumn)); var arrayOfColumn = (ArrayOfColumn)serializer.Deserialize(xmlReader); var myColumnList = arrayOfColumn.Columns; // 后续处理逻辑 }
这种方式最可靠,XmlSerializer会自动处理所有Column元素,兼容两种XML格式。
方法二:改用XmlReader.Read()遍历节点
如果不想新增类,可以调整遍历方式,手动检查节点:
using (var xmlReader = XmlReader.Create(fileStream)) { var serializer = new XmlSerializer(typeof(MyColumnClass), new XmlRootAttribute("Column")); var myColumnList = new List<MyColumnClass>(); while (xmlReader.Read()) { // 仅当遇到名为Column的元素节点时反序列化 if (xmlReader.NodeType == XmlNodeType.Element && xmlReader.Name == "Column") { myColumnList.Add((MyColumnClass)serializer.Deserialize(xmlReader)); } } // 后续处理逻辑 }
这种方式通过逐节点遍历,确保不会错过任何Column元素,适配两种XML格式。
内容的提问来源于stack exchange,提问作者Shahar Shokrani
相关产品推荐
相关产品推荐

