C# XmlElement数组序列化多余嵌套层级问题求助
解决XML序列化中节点直接包含元素的问题
嘿,我明白你现在的困扰——用XmlElement[]存储plate元素后,序列化出来每个plate都被<XmlElement>包裹,而你想要它们直接在<cars>节点下排列对吧?这其实是XmlSerializer默认行为导致的,咱们用一个简单的特性就能搞定。
问题出在哪?
默认情况下,当你把XmlElement[]作为类的属性时,XmlSerializer会把数组里的每个元素都包装在<XmlElement>标签里,这就是为什么你看到了多余的嵌套。我们需要告诉序列化器:“直接把这些元素放到<cars>节点下面,别加额外包装!”
怎么解决?
核心就是用**[XmlAnyElement]特性**,它能让XmlSerializer把数组里的每个XmlElement直接嵌入指定的父节点中。下面是修改后的完整代码,我会标注关键改动:
修改后的完整代码
using System; using System.Collections.Generic; using System.IO; using System.Text; using System.Xml; using System.Xml.Serialization; using Xunit; using Xunit.Abstractions; namespace TestsProjec.XML { public class Tests { private readonly ITestOutputHelper _testOutputHelper; public Tests(ITestOutputHelper testOutputHelper) { _testOutputHelper = testOutputHelper; } [Fact] public void InjectingXml() { var serializer = new XmlSerializer(typeof(Garage)); var cars = new List<XmlElement>(); cars.Add(StringToXmlElement("<plate>ABC123</plate>")); cars.Add(StringToXmlElement("<plate>DSC563</plate>")); cars.Add(StringToXmlElement("<plate>AIO789</plate>")); cars.Add(StringToXmlElement("<plate>IUE692</plate>")); string fullXml; var entity = new Garage() { owner = "Daniel", CarsElements = cars.ToArray() }; using (MemoryStream ms = new MemoryStream()) { // 可选:设置XmlWriter不生成UTF-8 BOM,避免手动跳过字节的麻烦 var writerSettings = new XmlWriterSettings { Encoding = new UTF8Encoding(false) }; using (XmlWriter tw = XmlWriter.Create(ms, writerSettings)) { serializer.Serialize(tw, entity); ms.Position = 0; fullXml = Encoding.UTF8.GetString(ms.ToArray()); } } _testOutputHelper.WriteLine(fullXml); } public XmlElement StringToXmlElement(string xml) { XmlDocument doc = new XmlDocument(); doc.LoadXml(xml); return doc.DocumentElement; } } [XmlRoot("Garage")] public class Garage { public string owner { get; set; } // 关键:用XmlAnyElement指定父节点名为cars,数组里的元素直接嵌入其中 [XmlAnyElement("cars")] public XmlElement[] CarsElements { get; set; } } }
关键改动说明
- 添加
[XmlAnyElement("cars")]特性:这个特性是核心,它告诉XmlSerializer把CarsElements数组里的每个XmlElement,直接作为<cars>节点的子元素输出,不会再套<XmlElement>标签。 - 调整属性名称:把原来的
cars属性改名为CarsElements(只是为了语义更清晰,你也可以保留原名,只要特性指定正确就行)。 - 优化流读取逻辑:原来手动跳过3字节的操作其实没必要,通过
XmlWriterSettings设置不生成UTF-8 BOM,就能直接读取整个流的内容,代码更简洁可靠。
最终效果
修改后序列化出来的XML会是你想要的样子:
<Garage xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <owner>Daniel</owner> <cars> <plate>ABC123</plate> <plate>DSC563</plate> <plate>AIO789</plate> <plate>IUE692</plate> </cars> </Garage>
这样<cars>节点下就直接排列<plate>标签了,完美符合你的需求!
内容的提问来源于stack exchange,提问作者Daniel Maiochi
相关产品推荐
相关产品推荐

