[英]Deserialize XML Fragment with Namespace using C#
我有問題反序列化以下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類中的名稱空間的屬性,但一切看起來都是正確的。 任何人都可以指出我正在犯的錯誤嗎?
該答案給出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();
}
}
}
我認為你需要對原始命名空間聲明one
。 這是因為one
是命名空間, OE
和List
類的項是前綴,它們存在於oneNote創建的命名空間中,聲明不存在於您發布的片段中。 存在前綴以避免在不同XML文檔混合在一起時命名中的沖突。 請參閱w3schools鏈接以獲取進一步說明
因此,解決方法是將名稱空間(例如<xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote">
附加到每個片段(似乎不是最優的,但是呃它有效),並且像你一樣去進行反序列化。
我沒有方便的OneNote,因此命名空間聲明來自此論壇帖子 。
另一種反序列化XML片段的方法是通過XMLReader和XMLReaderSettings,您可以在其中將coformance級別設置為Fragment 。 並添加預定義的命名空間。
從此MSDN博客改編的示例
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()
並進行設置,但它看起來更健壯。
或者 ,如果您不想處理自定義命名空間而不想處理碰撞問題,只需以編程方式刪除one:
的前端聲明,然后繼續反序列化它。 不過,這更像是字符串操作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.