我有一个包含以下格式的xml的Stream,我希望将其反序列化为C#对象
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<OrganisationMetaData xmlns="urn:organisationMetaDataSchema">
<Organisations>
<Organisation>
<Code>XXX</Code>
<Name>Yyyyyy</Name>...
我已经使用字符串完成了这么多次,但是对于流,它将命名空间属性附加到所有复杂元素。如果我只删除xmlns属性,并忘记根据模式验证它,它只是附加一个空的xmlns属性。我遇到的问题是XmlSerializer(?)中的Deserialize方法抛出一个错误,说它不期望该属性。我尝试使用XmlRoot和XmlType属性来修饰类,但这并没有改变任何内容。
这是我要反序列化的课程
[XmlRoot(
ElementName = "OrganisationMetaData",
Namespace = "urn:organisationMetaDataSchema")]
public class OrganisationMetaData
{
public List<Organisation> Organisations { get; set; }
}
[XmlType(
TypeName = "Organisation",
Namespace = "urn:organisationMetaDataSchema")]
public class Organisation
{
public string Code {get; set;}
public string Name {get; set;}
}
以下是用于完成工作的方法
public IList<Organisation> DeserializeOrganisations(Stream stream)
{
var serializer = new XmlSerializer(typeof(OrganisationMetaData));
var mappingAssembly = //Resource in another assembly
var schemas = new XmlSchemaSet();
schemas.Add(
"urn:organisationMetaDataSchema",
XmlReader.Create(
mappingAssembly.GetManifestResourceStream(
// An xml schema
)
)
);
var settings = new XmlReaderSettings()
{
ValidationType = ValidationType.Schema,
Schemas = schemas,
ValidationFlags =
XmlSchemaValidationFlags.ReportValidationWarnings
};
settings.ValidationEventHandler += settings_ValidationEventHandler;
var reader = XmlReader.Create(stream, settings);
var metaData= (OrganisationMetaData)serializer.Deserialize(reader);
return metaData.Organisations.ToList();
}
我已经尝试过使用DataContractSerializer,但它带来了自己的学习机会,所以如果有人可以帮助我应该放置属性以使XmlSerializer工作,那就太好了。
任何帮助都将不胜感激,谢谢。
答案 0 :(得分:1)
这里的关键是[XmlRoot]
只能应用于根类型,例如类;如果您使用List<>
作为根,它将无效 - 但我们可以使用[XmlElement]
来填充它。我正在使用Stream
方法(通过Encoding.UTF8
),但请注意,这不是问题的核心IMO(根类型):
[XmlRoot(Namespace="urn:organisationMetaDataSchema")]
public class Organisations
{
private readonly List<Organisation> items = new List<Organisation>();
[XmlElement("Organisation")]
public List<Organisation> Items { get { return items; } }
}
public class Organisation
{
public string Code { get; set; }
public string Name { get; set; }
}
static class Program
{
static void Main()
{
string xml = @"<?xml version='1.0' encoding='utf-8' standalone='yes'?><Organisations xmlns='urn:organisationMetaDataSchema'><Organisation><Code>XXXX</Code><Name>YYYYYYYY</Name></Organisation></Organisations>";
XmlSerializer ser = new XmlSerializer(typeof(Organisations));
using (Stream input = new MemoryStream(Encoding.UTF8.GetBytes(xml)))
{
Organisations orgs = (Organisations)ser.Deserialize(input);
}
}
}
答案 1 :(得分:0)
我最后更改了代码以使用数据协定序列化程序,它给了我更明显的命名空间错误,允许我有一个读取器根据模式验证xml流,然后回滚流并在另一个中再次使用它将xml反序列化的读者。
阅读this question提醒我一个问题,其中xml元素必须按字母顺序排列。我还发现当反序列化我的类的属性是一个枚举时,我需要要求它存在(它毕竟不可为空)。
这导致了另一个错误,其中我有一个xml节点,其中省略了一些值(我的架构确定),但是数据契约期望它们按顺序排列,所以我必须明确指定它。
我最终得到了像这样的数据成员属性
[DataMember(
Name = "MyEnumType",
EmitDefaultValue = false,
IsRequired = true,
Order = 3)]
//Just assume I added this prop after my Code, and Name properties from above
感谢Marc花时间看这个。