我遇到了反序列化以下XML片段(来自OneNote)的问题:
<one:OE creationTime="2015-03-21T18:32:38.000Z" lastModifiedTime="2015-03-21T18:32:38.000Z" objectID="{649CA68C-C596-4F89-9885-1553A953529E}{30}{B0}" alignment="left" quickStyleIndex="1" selected="partial">
<one:List>
<one:Bullet bullet="2" fontSize="11.0" />
</one:List>
<one:T><![CDATA[Bullet point one]]></one:T>
</one:OE>
以下代码用于反序列化上述片段。 OE类具有以下属性:
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.34230")]
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://schemas.microsoft.com/office/onenote/2013/onenote")]
[System.Xml.Serialization.XmlRootAttribute("OE", Namespace = "http://schemas.microsoft.com/office/onenote/2013/onenote", IsNullable = true)]
public partial class OE : EntityBase<OE>
{
...
}
反序列化片段的实际方法是在基类EntityBase:
中public static T Deserialize(string xml)
{
System.IO.StringReader stringReader = null;
try
{
stringReader = new System.IO.StringReader(xml);
return ((T)(Serializer.Deserialize(System.Xml.XmlReader.Create(stringReader))));
}
finally
{
if ((stringReader != null))
{
stringReader.Dispose();
}
}
}
deserialize方法调用如下:
var element = OE.Deserialize(xmlString);
变量xmlString
是上面给出的XML片段。在调用Deserialize
方法时,我收到以下错误:
There is an error in XML document (1,2). ---> System.Xml.XmlException: 'one' is an undeclared prefix. Line 1, position 2.
我花了一些时间查看声明OE类中名称空间的属性,但一切看起来都是正确的。谁能指出我正在犯的错误?
答案 0 :(得分:2)
answer给出的matrixanomaly是正确的,但不幸的是,给出的OneNote命名空间不正确。我正在使用OneNote 2013而不是2010.我用来反序列化我在问题中给出的相同XML片段的实际代码如下:
public static OE DeserializeFragment(string xmlFragment)
{
var serializer = new System.Xml.Serialization.XmlSerializer(typeof(OE));
System.IO.StringReader stringReader = null;
try
{
stringReader = new System.IO.StringReader(xmlFragment);
NameTable nt = new NameTable();
XmlNamespaceManager nsManager = new XmlNamespaceManager(nt);
nsManager.AddNamespace("one", "http://schemas.microsoft.com/office/onenote/2013/onenote");
XmlParserContext context = new XmlParserContext(null, nsManager, null, XmlSpace.None);
XmlReaderSettings xmlReaderSettings = new XmlReaderSettings();
xmlReaderSettings.ConformanceLevel = ConformanceLevel.Fragment;
return ((OE)(serializer.Deserialize(System.Xml.XmlReader.Create(stringReader, xmlReaderSettings, context))));
}
finally
{
if ((stringReader != null))
{
stringReader.Dispose();
}
}
}
答案 1 :(得分:1)
我认为您需要one
的原始名称空间声明。这是因为one
是一个命名空间,OE
和List
之类的项是前缀,它们存在于oneNote创建的命名空间中,声明不会出现在片段中发布。存在前缀以避免在不同XML文档混合在一起时命名中的冲突。 see a w3schools link for further explanation
因此,解决方法是将<xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote">
这样的命名空间附加到每个片段(似乎不是最优的,但是它可以工作),然后按照你的方式对其进行反序列化。已完成。
我没有方便的OneNote,因此名称空间声明为from this forum post。
反序列化XML片段的另一种方法是通过 XMLReader 和XMLReaderSettings,您可以将coformance级别设置为 Fragment 。并添加一个预定义的命名空间。
的示例 XmlDocument doc = new XmlDocument();
NameTable nt = new NameTable();
XmlNamespaceManager nsmgr = new XmlNamespaceManager(nt);
nsmgr.AddNamespace("one", "http://schemas.microsoft.com/office/onenote/2010/onenote");
XmlParserContext context = new XmlParserContext(null, nsmgr, null, XmlSpace.None);
XmlReaderSettings xset = new XmlReaderSettings();
xset.ConformanceLevel = ConformanceLevel.Fragment;
XmlReader rd = XmlReader.Create(new StringReader(XMLSource), xset, context);
doc.Load(rd);
我个人更喜欢使用XMLReader和XMLReader设置,虽然它们似乎需要更多工作CreateReader()
并进行设置,但它看起来更加强大。
或,如果您不想处理自定义命名空间而不想处理碰撞问题,请以编程方式删除{的前端声明{1}},继续反序列化。不过,这更像是字符串操作。