【问题标题】:Why is XmlReader appending namespace uris to each element?为什么 XmlReader 将命名空间 uris 附加到每个元素?
【发布时间】:2011-01-23 15:48:31
【问题描述】:

我有一个包含以下格式的 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 工作,那就太好了。

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

【问题讨论】:

    标签: c# xml serialization xmlreader xmlserializer


    【解决方案1】:

    这里的关键是[XmlRoot]只能应用于类等根类型;如果您使用List&lt;&gt; 作为根,它将无法正常工作 - 但我们可以使用[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);
            }
        }
    }
    

    【讨论】:

    • 谢谢 Marc,我现在对此有点脑残。我的 xml 没有您的字符串所具有的单引号。您将如何克服这个问题,就像 Replace(...) 一样简单?
    • 我已经尝试了所有我能想到的,所以大约 8 小时后,我放弃了,转而使用 DataContractSerializer,它可以告诉我更多关于它的信息不喜欢xml。感谢您的帮助马克 :)
    • @Mark - 单引号无关紧要。发布的代码应该反序列化您引用的 xml。您可以发布(或发送电子邮件,如果您愿意)您的课程吗?我很确定我可以告诉你出了什么问题......
    • 我这里有一些限制。将代码发布出来,但我会拼凑一些东西以获得一个体面的答案。我发现的问题是,如果我把我的流变成一个字符串,它在双引号、换行符和返回之前有转义字符。我不知道这些是从哪里来的。我已经开始使用 DataContractSerializer,但这与 Organizations 对象有关,即使我将它包装在另一个对象中也是如此。
    • 我已经切换到 DataContractSerializer,它也可能对我有更长远的帮助,在找到这个答案 (stackoverflow.com/questions/1651010) 之后,我让它运行良好。如果您想继续解决 XmlSerializer 的问题并且需要我提供任何信息,请告诉我。干杯
    【解决方案2】:

    我最终更改了代码以使用数据协定序列化程序,它给了我围绕命名空间的更明显的错误,这使我能够拥有一个阅读器来根据架构验证 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 抽出宝贵时间查看此内容。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-11-17
      • 2017-11-27
      • 1970-01-01
      • 1970-01-01
      • 2010-09-13
      • 1970-01-01
      • 1970-01-01
      • 2011-02-10
      相关资源
      最近更新 更多