1

我有一个包含以下格式的 xml 的流,我想将其反序列化为 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 工作,那就太好了。

任何帮助将不胜感激,谢谢。

4

2 回答 2

1

这里的关键是[XmlRoot]只能应用于类等根类型;如果您使用 aList<>作为根,它将不起作用 - 但我们可以使用[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);
        }
    }
}
于 2010-03-04T12:15:41.283 回答
0

我最终将代码更改为使用数据合同序列化程序,它给了我围绕命名空间的更明显的错误,这使我能够拥有一个阅读器,该阅读器根据架构验证 xml 流,然后倒回流并在另一个反序列化的阅读器中再次使用它xml。

阅读这个问题提醒我注意一个问题,其中 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 花时间看这个。

于 2010-03-09T16:30:06.843 回答