我尝试在一次传递中处理大型XML文档(使用XmlReader
),并使用XmlSerializer
仅对其中的某些元素进行反序列化。
下面是一些代码和一个微小的模拟XML文档,显示了我是如何尝试这样做的。
使用
XmlReader
的基本原理: 1。我正在处理非常大的XML文档(10-250 MB),因此我不想加载到内存中。所以XmlDocument
是不可能的。 2。我想只提取某些元素。通常,我将能够忽略大多数其他内容。XmlReader
似乎为我提供了一种跳过不相关内容的有效方法。 3。我事先并不知道我能处理的所有元素是否存在;因此,我没有使用一堆Xpath
/XQuery
或LINQ to XML查询,因为我只想对XML文件进行一次传递(由于它们的大小)。
public class ElementOfInterest { }
…
var xml = @"<?xml version='1.0' encoding='utf-8' ?>
<Root xmlns:ex='urn:stakx:example'
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>
<ElementOfInterest xsi:type='ex:ElementOfInterest' />
</Root>";
var reader = System.Xml.XmlReader.Create(new System.IO.StringReader(xml));
reader.ReadToFollowing("ElementOfInterest");
var serializer = new System.Xml.Serialization.XmlSerializer(typeof(ElementOfInterest));
serializer.Deserialize(reader.ReadSubtree());
最后一行代码抛出以下内部异常:
InvalidOperationException
:&#34;未定义命名空间前缀ex
。&#34;
显然,XmlSerializer
无法识别ex
属性值中的xsi:type
名称空间前缀。
这只是我遇到的一个错误,但坦率地说,更大的问题是我不知道如何解决整个命名空间问题。我只是在寻找一种方便的方法来从XML文档中反序列化单个节点,但这似乎需要手动注册/管理命名空间,并以某种方式将它们从XmlReader
转发到{ {1}}。
有人可以演示如何从使用XmlSerializer
读取的XML文档中反序列化单个节点,方法是指出代码中的错误,或者通过显示替代方法?
答案 0 :(得分:6)
以下作品:
using System.IO;
using System.Xml;
using System.Xml.Serialization;
static void Main()
{
var xml = @"<?xml version='1.0' encoding='utf-8' ?>
<Root
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xmlns:ex='urn:stakx:example'
>
<ex:ElementOfInterest xsi:type='ex:ElementOfInterest' />
</Root>";
var nt = new NameTable();
var mgr = new XmlNamespaceManager(nt);
mgr.AddNamespace("ex", "urn:stakx:example");
var ctxt = new XmlParserContext(nt, mgr, "", XmlSpace.Default);
var reader = XmlReader.Create(new StringReader(xml), null, ctxt);
var serializer = new XmlSerializer(typeof(ElementOfInterest));
reader.ReadToFollowing("ElementOfInterest", "urn:stakx:example");
var eoi = (ElementOfInterest)serializer.Deserialize(reader.ReadSubtree());
}
[XmlRoot(Namespace = "urn:stakx:example")]
public class ElementOfInterest { }
请注意输入中的命名空间:<ex:ElementOfInterest>
。