簡體   English   中英

使用C#中的XmlSerializer.Deserialize()反序列化父命名空間之外的子節點

[英]Deserializing child nodes outside of parent's namespace using XmlSerializer.Deserialize() in C#

我有一個應用程序,它使用命名空間來幫助反序列化存儲在XML中的對象。 XML命名空間也是對象所在的C#命名空間。 例如,給定以下XML剪輯:

<xml-config xmlns:app="MyAppNS">
  <app:Person>
    <Name>Bill</Name>
    <Car>
      <Make>Honda</Make>
      <Model>Accord</Model>
    </Car>
  </app:Person>

  <app:Person>
    <Name>Jane</Name>
    <Car>
      <Make>VW</Make>
      <Model>Jetta</Model>
    </Car>
  </app:Person>

  <app:Car>
    <Make>Audi</Make>
    <Model>A6</Model>
  </app:Car>
</xml-config>

配置實際上只是一個隨機的對象包。 如您所見,頂層有PersonCar對象的混合。 我使用命名空間在加載時確定對象類型以進行正確的反序列化。 以下是加載文檔的代碼:

public static void LoadFile(String file) {
    XmlDocument doc = new XmlDocument();
    doc.Load(file);

    XmlNode root = doc.DocumentElement;
    foreach (XmlNode child in root.ChildNodes) {
        if (child.NodeType != XmlNodeType.Element) {
            continue;
        }

        Object obj = LoadObject(child);
        // TODO handle object here...
    }
}

private static Object LoadObject(XmlNode node) {
    Object obj = null;

    StringBuilder str = new StringBuilder();
    if ((node.Prefix != null) && (node.Prefix != "")) {
        str.Append(node.NamespaceURI).Append('.');
    }
    str.Append(node.LocalName);

    Assembly assy = Assembly.GetExecutingAssembly();
    Type type = assy.GetType(str.ToString());
    XmlSerializer serdes = new XmlSerializer(type);

    using (XmlNodeReader reader = new XmlNodeReader(node)) {
        obj = serdes.Deserialize(reader);
    }

    return obj;
}

很多人立即看到了這個問題,但是當使用這個代碼時,生成的Person對象是空的,但是沒有錯誤。 讓反序列化器填充子元素的唯一方法是為子元素使用相同的命名空間:

  <app:Person>
    <app:Name>Bill</app:Name>
    <app:Car>
      <app:Make>Honda</app:Make>
      <app:Model>Accord</app:Model>
    </app:Car>
  </app:Person>

我嘗試的唯一其他選項是使用完全限定的類型名稱作為元素名稱(沒有名稱空間),但是我沒有運氣。 有沒有辦法讓反序列化器接受XML節點的非前綴子節點?

我終於找到了一種方法來完成這個,修改了這里找到的答案。

我創建了一個自定義反序列化器,它復制起始節點的命名空間:

public class CustomXmlNodeReader : XmlNodeReader {

    private String _namespace;

    public CustomXmlNodeReader(XmlNode node) : base(node) {
        _namespace = node.NamespaceURI;
    }

    public override String NamespaceURI {
        get { return _namespace; }
    }
}

使用此閱讀器,我可以使用以下內容加載存儲的對象:

using (XmlNodeReader reader = new CustomXmlNodeReader(node)) {
    obj = serdes.Deserialize(reader);
}

我知道這對於XML來說是一個糟糕的形式(強制應用特定的命名空間),但它非常適合我的需求。 在這里回答,以防它幫助其他人。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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