How to deserialize a node in a large document using XmlSerializer(如何使用 XmlSerializer 反序列化大型文档中的节点)
问题描述
我有一个大型 XML 文档,已加载到 XmlDocument
中,我想使用 XmlSerializer
类将其中的选定元素反序列化为生成的 .NET 类使用 xsd.exe.
I have a large XML document that I have loaded into an XmlDocument
and I want to use the XmlSerializer
class to deserialize selected elements from it into a .NET class generated using xsd.exe.
这是迄今为止我尝试过的 MCVE;xsd 和生成的类在帖子的末尾.如代码中的注释中所述,我得到一个 InvalidOperationException
- <Cars xmlns:'http://MyNamespace'/>没想到
:
Here's an MCVE of what I've tried so far; the xsd and generated class are at the end of the post. As noted in the comments in the code, I am getting an InvalidOperationException
- <Cars xmlns:'http://MyNamespace' /> was not expected
:
我还想随后更新我的 Car
类实例,并使用 XmlSerializer
将其插入回文档中,这是后续问题的主题 如何使用 XmlSerializer 在大文档中插入节点.
I also want to subsequently update my Car
class instance, and insert it back into the document using the XmlSerializer
, which is the subject of a follow-up question How to insert a node in a large document using XmlSerializer
.
xsd 和生成的类如下:
The xsd and generated classes follow:
xsd.exe 生成的代码:
Code generated by xsd.exe:
推荐答案
这里有两个问题:
var node = doc.DocumentElement.SelectSingleNode("myns:Cars", nsMgr);
位于
元素——<Car>
节点的重复序列的容器元素 - 但您的XmlSerializer
被构造为反序列化名为<Car>.尝试使用反序列化单个汽车的序列化程序反序列化一系列汽车是行不通的.
The var node = doc.DocumentElement.SelectSingleNode("myns:Cars", nsMgr);
is positioned at the <Cars>
element -- the container element for the repeating sequence of <Car>
nodes -- but your XmlSerializer
is constructed to deserialize a single root element named <Car>
. Trying to deserialize a sequence of cars with a serializer constructed to deserialize a single car will not work.
出于某种原因,xsd.exe
为您的 Car
类型生成了一个定义,但没有 XmlRoot
属性:
For some reason xsd.exe
generated a definition for your Car
type without an XmlRoot
attribute:
因此,如果您尝试将 Car
作为 XML 文档的根 XML 元素序列化或反序列化,那么 XmlSerializer
将期望该根元素不在任何命名空间中.大型文档中的每个 <Car>
节点都位于 "http://MyNamespace"
默认命名空间中,因此尝试单独反序列化每个节点也行不通.
Thus if you attempt to serialize or deserialize a single instance of a Car
as the root XML element of an XML document then XmlSerializer
will expect that root element to not be in any namespace. Each <Car>
node in your large document is in the "http://MyNamespace"
default namespace, so attempting to deserialize each one individually also will not work.
您可以手动将缺少的 [XmlRoot(Namespace = "http://MyNamespace")]
属性添加到 Car
,但这样做可能会很麻烦如果随后修改了 XSD 文件并且需要重新生成 c# 类型.
You could manually add the missing [XmlRoot(Namespace = "http://MyNamespace")]
attribute to Car
, but having to do this can be a nuisance if the XSD files are subsequently modified and the c# types need to be regenerated.
要避免这两个问题,您可以使用 XmlNode.SelectNodes(String, XmlNamespaceManager)
选择
元素内的每个
节点,然后通过 构造一个带有重写 XmlRootAttribute 的 XmlSerializer
带有被反序列化的节点的元素名称和命名空间.首先,定义如下扩展方法:
To avoid both issues, you can use XmlNode.SelectNodes(String, XmlNamespaceManager)
to select every <Car>
nodes inside the <Cars>
element, then deserialize each one by constructing an XmlSerializer
with an override XmlRootAttribute
with the element name and namespace of the node being deserialized. First, define the following extension methods:
然后反序列化如下:
如此答案 Marc Gravell.
示例工作 .Net fiddle.
这篇关于如何使用 XmlSerializer 反序列化大型文档中的节点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!