数组的C#XML反序列化

数组的C#XML反序列化,c#,xml,arrays,C#,Xml,Arrays,我对反序列化数组有一个问题。因为数组元素可以是各种类型。您可以看到以下示例: <?xml version="1.0" encoding="UTF-8"?><export xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://zakupki.gov.ru/oos/export/1" xmlns:oos="http://zakupki.gov.ru/oos/types/1"> <notif

我对反序列化数组有一个问题。因为数组元素可以是各种类型。您可以看到以下示例:

<?xml version="1.0" encoding="UTF-8"?><export xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://zakupki.gov.ru/oos/export/1" xmlns:oos="http://zakupki.gov.ru/oos/types/1">
<notificationZK>
    ... item 1 data
</notificationZK>
<notificationZK>
    ... item 2 data
</notificationZK>
<notificationFF>
    ... item 3 data
</notificationFF>
</export>
因此,问题是如何从XML文件中获取
notificationType
元素的集合?我想我不能做像这样的事情

[Serializable()]
[System.Xml.Serialization.XmlRoot("export")]
public class NotificationCollection
{
    [XmlArray("")] // ???? what I need write here?
    [XmlArrayItem("", typeof(notificationType))] // ??? and here?
    public notificationType[] notification { get; set; }
}
问候

增加-------------

所以。我要这样做:

[Serializable()]
[System.Xml.Serialization.XmlRoot("export")]
public class NotificationCollection
{
    [XmlElement("notificationSZType", Type = typeof(notificationSZType))]
    [XmlElement("notificationPOType", Type = typeof(notificationPOType))]
    [XmlElement("notificationZKType", Type = typeof(notificationZKType))]
    [XmlElement("notificationEFType", Type = typeof(notificationEFType))]
    [XmlElement("notificationOKType", Type = typeof(notificationOKType))]
    public notificationType[] notification { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        NotificationCollection collection = null;
        string path = @"E:\notification.xml";
        XmlSerializer serializer = new XmlSerializer(typeof(notificationType));
        StreamReader reader = new StreamReader(path);
        collection = (NotificationCollection) serializer.Deserialize(reader);
        reader.Close();

    }
}
但have System.invalidoOperationException在
序列化程序.反序列化(读取器)时未处理

Message=不需要。

我做错了什么?

将类型声明移动到集合中如何

[XmlRoot("export")]
public class NotificationCollection
{

  [XmlElement("notificationZK", typeof(NotificationTypeZK))]
  [XmlElement("notificationFF", typeof(NotificationTypeFF))]
  public List<NotificationType> Notifications { get; set; }

}

public class NotificationType
{

}

public class NotificationTypeZK : NotificationType { }

public class NotificationTypeFF : NotificationType { }

static void Main(string[] args)
{
  var data = @"<export><notificationZK /><notificationZK /><notificationFF /></export>";

  var serializer = new XmlSerializer(typeof(NotificationCollection));

  using (var reader = new StringReader(data))
  {
    var notifications = serializer.Deserialize(reader);
  }
}
[XmlRoot(“导出”)]
公共类通知集合
{
[XmlElement(“notificationZK”,typeof(NotificationTypeZK))]
[XmlElement(“notificationFF”,类型化(NotificationTypeFF))]
公共列表通知{get;set;}
}
公共类通知类型
{
}
公共类NotificationTypeZK:NotificationType{}
公共类NotificationTypeFF:NotificationType{}
静态void Main(字符串[]参数)
{
var数据=@;
var serializer=新的XmlSerializer(typeof(NotificationCollection));
使用(变量读取器=新的StringReader(数据))
{
var通知=序列化程序。反序列化(读取器);
}
}

这应该可以完成这项工作

    [Serializable()]
    [System.Xml.Serialization.XmlRoot("export")]
    public class NotificationCollection
    {
        [XmlElement("notificationSZType", Type = typeof(notificationSZType))]
        [XmlElement("notificationPOType", Type = typeof(notificationPOType))]
        [XmlElement("notificationZKType", Type = typeof(notificationZKType))]
        [XmlElement("notificationEFType", Type = typeof(notificationEFType))]
        [XmlElement("notificationOKType", Type = typeof(notificationOKType))]
        public notificationType[] notification { get; set; }
    }

这个问题对我来说也很有趣。我编写了简化应用程序来实现您的要求:

[Serializable]
[XmlInclude(typeof(ItemA))]
[XmlInclude(typeof(ItemB))]
public class BaseItem
{
    public bool Value { get; set; }
}

[Serializable]
public class ItemA : BaseItem
{
    public string Text { get; set; }
}

[Serializable]
public class ItemB : BaseItem
{
    public int Number { get; set; }
}

[Serializable]
public class ItemsArray
{
    public BaseItem[] Items { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        var array = new ItemsArray
        {
            Items = new BaseItem[]
            {
                new ItemA { Value = true, Text = "Test" },
                new ItemB { Value = false, Number = 7 }
            }
        };

        ItemsArray output;

        using (var stream = new MemoryStream())
        {
            var serializer = new XmlSerializer(typeof(ItemsArray));
            serializer.Serialize(stream, array);

            stream.Position = 0;
            output = (ItemsArray)serializer.Deserialize(stream);
        }
    }
}
反序列化之后,我们得到的正是我们序列化的内容。流中的XML如下所示:

<?xml version="1.0"?>
<ItemsArray xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Items>
    <BaseItem xsi:type="ItemA">
      <Value>true</Value>
      <Text>Test</Text>
    </BaseItem>
    <BaseItem xsi:type="ItemB">
      <Value>false</Value>
      <Number>7</Number>
    </BaseItem>
  </Items>
</ItemsArray>

真的
试验
假的
7.
正如在另一个答案中提到的,您不能在XML数组中使用不同的标记。但是,仍然可以存储不同的类型。序列化程序通过使用
xsi:type
属性来实现这一点


为了解决您的问题,您可能需要使用另一种XML模式。

示例XML缺少开头标记。为什么缺少?这是我工作项目中的真实XML:(这里是真实文件的示例:忽略我。我误读了:(我测试了你的3个答案,它们都有效。但它对我不起作用:(我从XSD生成了C#类。XSD可以在这里下载。可能的生成类丢失了?如果导出的格式不固定,我也会使用这种方法。根据您的模式,具有不同的子元素标记名是有效的XML。保留问题中定义的模式时,可以解决此问题。@Gusdor如果元素未知,我如何实现它?在OP的情况下,元素的名称是已知的。在我的情况下,我不能执行[XmlElement(“notificationOKType”,Type=typeof(notificationOKType))]公共notificationType[]通知{get;set;}因为元素“notificationOKType”可以有任何name@wintersolstice这是可能的(而且是直截了当的),但你应该提出另一个问题。
[Serializable]
[XmlInclude(typeof(ItemA))]
[XmlInclude(typeof(ItemB))]
public class BaseItem
{
    public bool Value { get; set; }
}

[Serializable]
public class ItemA : BaseItem
{
    public string Text { get; set; }
}

[Serializable]
public class ItemB : BaseItem
{
    public int Number { get; set; }
}

[Serializable]
public class ItemsArray
{
    public BaseItem[] Items { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        var array = new ItemsArray
        {
            Items = new BaseItem[]
            {
                new ItemA { Value = true, Text = "Test" },
                new ItemB { Value = false, Number = 7 }
            }
        };

        ItemsArray output;

        using (var stream = new MemoryStream())
        {
            var serializer = new XmlSerializer(typeof(ItemsArray));
            serializer.Serialize(stream, array);

            stream.Position = 0;
            output = (ItemsArray)serializer.Deserialize(stream);
        }
    }
}
<?xml version="1.0"?>
<ItemsArray xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Items>
    <BaseItem xsi:type="ItemA">
      <Value>true</Value>
      <Text>Test</Text>
    </BaseItem>
    <BaseItem xsi:type="ItemB">
      <Value>false</Value>
      <Number>7</Number>
    </BaseItem>
  </Items>
</ItemsArray>