简体   繁体   English

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

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

I have an application that uses namespaces to help deserialize objects stored in XML. 我有一个应用程序,它使用命名空间来帮助反序列化存储在XML中的对象。 The XML namespace is also the C# namespace where the object resides. XML命名空间也是对象所在的C#命名空间。 For example, given the following XML snip: 例如,给定以下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>

The configuration is really just a random bag of objects. 配置实际上只是一个随机的对象包。 As you can see, there is a mix of Person and Car objects at the top level. 如您所见,顶层有PersonCar对象的混合。 I use the namespace to determine the object type at load time for proper deserialization. 我使用命名空间在加载时确定对象类型以进行正确的反序列化。 Here is the code for loading the document: 以下是加载文档的代码:

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;
}

You many see the issue right away, but when this code is used, the resulting Person objects are empty, however there are no errors. 很多人立即看到了这个问题,但是当使用这个代码时,生成的Person对象是空的,但是没有错误。 The only way to get the deserializer to populate the child elements is to use the same namespace for the child elements: 让反序列化器填充子元素的唯一方法是为子元素使用相同的命名空间:

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

The only other option I have tried is to use fully-qualified type names as the element name (no namespaces), however I haven't had any luck with that. 我尝试的唯一其他选项是使用完全限定的类型名称作为元素名称(没有名称空间),但是我没有运气。 Is there a way to cause the deserializer to accept the non-prefixed children of the XML node? 有没有办法让反序列化器接受XML节点的非前缀子节点?

I finally found a method to accomplish this, modifying the answer found here . 我终于找到了一种方法来完成这个,修改了这里找到的答案。

I created a custom deserializer that replicates the namespace for the starting node: 我创建了一个自定义反序列化器,它复制起始节点的命名空间:

public class CustomXmlNodeReader : XmlNodeReader {

    private String _namespace;

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

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

Using this reader, I am able to load stored objects with the following: 使用此阅读器,我可以使用以下内容加载存储的对象:

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

I know this is a bit bad form for XML (forcing the application of a specific namespace), however it suits my needs quite nicely. 我知道这对于XML来说是一个糟糕的形式(强制应用特定的命名空间),但它非常适合我的需求。 Answered here in case it helps anyone else. 在这里回答,以防它帮助其他人。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 来自Socket c#的XmlSerializer.Deserialize() - XmlSerializer.Deserialize() from Socket c# 反序列化 XML 文件使用 XmlSerializer.Deserialize 从 MemoryStream 不起作用 - Deserializing XML File using XmlSerializer.Deserialize from MemoryStream not working 反序列化大型XML文档中的单个元素:由于名称空间问题,xmlSerializer.Deserialize(xmlReader.ReadSubtree())失败 - Deserializing a single element in a large XML document: xmlSerializer.Deserialize(xmlReader.ReadSubtree()) fails due to namespace issues C#解决XmlSerializer.Deserialize陷阱? - C# work around for XmlSerializer.Deserialize pitfall? XmlSerializer.Deserialize()没有反序列化List <T> 正确地 - XmlSerializer.Deserialize() isn't deserializing a List<T> correctly 使用xmlSerializer.Deserialize读取字符串 - using xmlSerializer.Deserialize to read a string XmlSerializer.Deserialize List &lt;&gt;项目 - XmlSerializer.Deserialize on a List<> item 何时使用XmlSerializer.Deserialize进行反序列化时调用类构造函数? - When is the class constructor called while deserialising using XmlSerializer.Deserialize? C#中的XmlSerializer /反序列化 - XmlSerializer/Deserialize in C# 如何使用XmlSerializer将异构子节点反序列化为集合? - How can I deserialize heterogeneous child nodes into a collection, using XmlSerializer?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM