簡體   English   中英

使用C#使用命名空間反序列化XML片段

[英]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是命名空間, OEList類的項是前綴,它們存在於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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM