【发布时间】:2021-07-16 09:30:55
【问题描述】:
(详情请见this demo)
假设我有一个这样的 XML 文件:
<?xml version="1.0" encoding="utf-16"?>
<Container>
<SomeValue>1</SomeValue>
<Item>
<Containers>
<Container>
<SomeValue>2</SomeValue>
<Item>
<!-- etc... -->
</Item>
</Container>
<Container>
<SomeValue>3</SomeValue>
</Container>
</Containers>
</Item>
</Container>
其中名为Container 的类包含一个Item,而名为Item 的类可以有许多子容器。
Container 类实现了IXmlSerializable(原因见注释),它有以下方法:
public void ReadXml(XmlReader reader)
{
XElement root = XElement.Load(reader.ReadSubtree());
this.SomeValue = (int)root.Element("SomeValue");
XElement itemElt = root.Element("Item");
if (itemElt == null)
{
// Empty container
return;
}
XmlSerializer xmlSerializer = new XmlSerializer(typeof(Item));
using (var itemReader = itemElt.CreateReader())
{
this.Item = (Item)xmlSerializer.Deserialize(itemReader);
}
}
但是,即使在其Containers 节点中有多个容器,运行此操作也会导致根容器的项目仅包含第一个容器(其中 SomeValue 为 2)。
那么为什么会跳过其他容器,我该如何解决呢?
我假设这是对 ReadSubtree() 的调用的问题,但忽略它会给我:
InvalidOperationException: The XmlReader state should be EndOfFile after this operation.
一些注意事项:
我必须使用IXmlSerializable 的原因是因为实际的“项目”类型是从数据库中获取的,具体取决于元素的名称。所以当我打电话给new XmlSerializer(typeof(Item))时,我实际上是在打电话给new XmlSerializer(specificItemType)。
此外,我更愿意尽可能多地使用System.Xml.Linq,因为它非常易读(而且我对 XML 的东西还很陌生)。它还允许我从树中的任何位置获取数据,而无需重新读取整个文档,我在实际代码中做了一些工作。但是,如果一定要走,我愿意放弃。
【问题讨论】:
标签: c# xml linq recursion deserialization