反序列化 a:anyType 的列表
Deserializing a List of a:anyType
我有一个由另一个应用程序提供的现有 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
反序列化的 class,目前看起来像这样:
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
列表 - 它始终为空。我尝试通过以下方式用 XmlAttributes
装饰 Group
中的 Elements
属性:
[XmlArrayItem(ElementName = "a")]
[XmlArrayItem(ElementName = "a:anyType")]
[XmlArrayItem(ElementName = "a", Type = typeof(SomeType))]
[XmlArrayItem(ElementName = "a:anyType", Type = typeof(SomeType))]
到目前为止,没有任何效果。
有人知道将 <a:anyType i:type="SomeType">
项反序列化到 Elements
列表中的正确方法吗?
编辑
从那以后我意识到我遗漏了我的问题是 <Root>
实际上有一个命名空间:<Root xmlns="http://someNameSpace">
。参见上文 XML。
考虑到您 xml 在 Root 上添加了名称空间声明
<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);
}
}
经过多次尝试让 XmlSerializer
工作后,我最终更改为 DataContractSerializer
,它首先用于进行序列化。
实现 DataContractSerializer
后,我必须提供接口 ISomeType
,并将 Elements
更新为 ISomeType
而不是 SomeType
的列表,以匹配 <a:anyType i:type="SomeType">
XML 元素
最终的 class 结构如下所示:
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);
}
}
我有一个由另一个应用程序提供的现有 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
反序列化的 class,目前看起来像这样:
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
列表 - 它始终为空。我尝试通过以下方式用 XmlAttributes
装饰 Group
中的 Elements
属性:
[XmlArrayItem(ElementName = "a")]
[XmlArrayItem(ElementName = "a:anyType")]
[XmlArrayItem(ElementName = "a", Type = typeof(SomeType))]
[XmlArrayItem(ElementName = "a:anyType", Type = typeof(SomeType))]
到目前为止,没有任何效果。
有人知道将 <a:anyType i:type="SomeType">
项反序列化到 Elements
列表中的正确方法吗?
编辑
从那以后我意识到我遗漏了我的问题是 <Root>
实际上有一个命名空间:<Root xmlns="http://someNameSpace">
。参见上文 XML。
考虑到您 xml 在 Root 上添加了名称空间声明
<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);
}
}
经过多次尝试让 XmlSerializer
工作后,我最终更改为 DataContractSerializer
,它首先用于进行序列化。
实现 DataContractSerializer
后,我必须提供接口 ISomeType
,并将 Elements
更新为 ISomeType
而不是 SomeType
的列表,以匹配 <a:anyType i:type="SomeType">
XML 元素
最终的 class 结构如下所示:
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);
}
}