反序列化一个 a:anyType 类型的列表

3

我有一个现有的XML文件,是由另一个应用程序提供的,看起来类似于这样:

<Root xmlns="http://someNameSpace">
    <DisplayName>RootName</DisplayName>
    <Groups>
        <Group>
            <Elements>
                <a:anyType i:type="SomeType">
                    <DisplayName>ElementName</DisplayName>
                </a>
            </Elements>
        </Group>
    </Groups>
</Root>

我正试图编写一个可以使用 XmlSerializer 进行反序列化的类,目前它看起来像这样:

public class Root
{
    public string DisplayName { get; set; }
    public List<Group> Groups { get; set; }
}

public class Group : SomeType
{
    public List<SomeType> Elements { get; set; }
}

public class SomeType
{
    public string DisplayName { get; set; }
}

以下是使用XmlSerializer进行简单反序列化的代码示例:

var serializer = new XmlSerializer(typeof (Root));
using (var streamReader = new StreamReader(somePathToXmlFile))
{
    root = (Root) serializer.Deserialize(streamReader);
}

一切都可以成功反序列化,只有Elements列表为空。我已经尝试在Group中用以下方式装饰Elements属性的XmlAttributes
  1. [XmlArrayItem(ElementName = "a")]
  2. [XmlArrayItem(ElementName = "a:anyType")]
  3. [XmlArrayItem(ElementName = "a", Type = typeof(SomeType))]
  4. [XmlArrayItem(ElementName = "a:anyType", Type = typeof(SomeType))]
到目前为止,什么都没有起作用。
有谁知道将<a:anyType i:type="SomeType">项反序列化到Elements列表的正确方法吗?
编辑: 我后来意识到我遗漏了一个问题,就是<Root>实际上有一个命名空间:<Root xmlns="http://someNameSpace">。请参见上面的XML。

我刚意识到我在标题中提到了Array,但是在代码中使用的是List:实际上我正在使用List。 - Phillip Parker
2个回答

1

考虑到您在根节点上添加了命名空间声明的xml

<Root xmlns:a="http://custom/a" xmlns:i="http://custom/i">
<DisplayName>RootName</DisplayName>
<Groups>
    <Group>
        <Elements>
          <a:anyType i:type="SomeType">
            <DisplayName>ElementName</DisplayName>
          </a:anyType>           
        </Elements>
    </Group>
</Groups>
</Root>

我已成功地使用以下xml属性对其进行反序列化:
public class Group : SomeType
{

    [XmlArrayItem(typeof(SomeType),ElementName = "anyType", Namespace = "http://custom/a")]
    public List<SomeType> Elements { get; set; }
}

public class SomeType
{
    [XmlElement(typeof(string),ElementName="DisplayName",Namespace="")]
    public string DisplayName { get; set; }
}

如果您无法向xml添加名称空间声明,请使用XmlNamespaceManager。
var serializer = new XmlSerializer(typeof(Root));
        var nameTable = new NameTable();
        var namespaceManager = new XmlNamespaceManager(nameTable);
        namespaceManager.AddNamespace("a", "http://custom/a");
        namespaceManager.AddNamespace("i", "http://custom/i");
        var parserContext = new XmlParserContext(null, namespaceManager, null, XmlSpace.None);
        var settings = new XmlReaderSettings()
        {
            ConformanceLevel = ConformanceLevel.Fragment

        };
        using(var fileStream=File.OpenRead(somePathToXmlFile))
        {
            using(var reader=XmlReader.Create(fileStream,settings,parserContext))
            {
                var root = (Root)serializer.Deserialize(reader);
            }
        }

谢谢您的回复。不幸的是,在我的情况下,那似乎并没有起作用。最终我使用了DataContractSerializer。 - Phillip Parker

0

尝试多次让XmlSerializer工作,最终我改用了DataContractSerializer,这也是最初用于序列化的。

实现DataContractSerializer后,我必须提供一个接口ISomeType,并将Elements更新为ISomeType列表而不是SomeType,以匹配<a:anyType i:type="SomeType"> XML元素。

最终的类结构如下:

public namespace Project
{
    [DataContract(Namespace = "http://someNameSpace")]
    public class Root
    {
        [DataMember]
        public string DisplayName { get; set; }

        [DataMember]
        public List<Group> Groups { get; set; }
    }

    [DataContract(Namespace = "http://someNameSpace")]
    public class Group : ISomeType
    {
        [DataMember]
        public List<ISomeType> Elements { get; set; }
    }

    [DataContract(Namespace = "http://someNameSpace")]
    public class SomeType : ISomeType
    {
        [DataMember]
        public string DisplayName { get; set; }
    }

    public interface ISomeType
    {
        string DisplayName { get; set; }
    }
}

反序列化代码:

using (var fileStream = new FileStream(somePathToXmlFile, FileMode.Open))
{
    using (var reader = XmlDictionaryReader.CreateTextReader(fileStream, new XmlDictionaryReaderQuotas()))
    {
        var serializer = new DataContractSerializer(typeof (Root));
        var root = (Root) serializer.ReadObject(reader, true);
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接