c# - 在 C# 中使用 XmlSerializer.Deserialize() 反序列化父命名空间之外的子节点

标签 c# xml serialization deserialization

我有一个应用程序使用命名空间来帮助反序列化存储在 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>

我尝试过的唯一其他选择是使用完全限定的类型名称作为元素名称(无 namespace ),但我没有成功。有没有办法让反序列化器接受 XML 节点的非前缀子节点?

最佳答案

我终于找到了一个方法来完成这个,修改找到的答案 here .

我创建了一个自定义反序列化器来复制起始节点的命名空间:

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 来说有点糟糕(强制应用特定 namespace ),但它非常适合我的需要。在这里回答,以防对其他人有帮助。

关于c# - 在 C# 中使用 XmlSerializer.Deserialize() 反序列化父命名空间之外的子节点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12765837/

相关文章:

c# - 在 WPF 包 URI 中使用通配符的替代方法

c# - 在各种技术之间传递数据

android - 在 Android 中为按钮组应用样式

Android:在同一 Activity 中更改布局

c# - 设置 OWIN 响应状态代码

java - 在首选项屏幕底部添加一个按钮

java - 获取详细的 json 响应(没有 id 引用,始终是实例)

c# - 非序列化属性创建错误

Android Parcelable 与 JsonObject

c# - 缓存 Linq 查询 - 这可能吗?