我有一个由另一个应用程序提供的现有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
列表外,所有内容都是反序列化的,它总是空的。我已尝试通过以下方式在Elements
Group
XmlAttributes
中装饰[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">
实际上有一个命名空间:{{1}}。见上面的XML。
答案 0 :(得分:1)
考虑在root上添加名称空间声明的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);
}
}
答案 1 :(得分: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);
}
}