简体   繁体   English

在 C# 中反序列化具有不同类型名称的 XML 元素

[英]Deserialize XML elements with different type name in C#

I'm stuck on how to solve the deserialization of this XML structure.我被困在如何解决这个 XML 结构的反序列化问题上。 The element "allocatables" have different types in the same namespace.元素“allocables”在同一个命名空间中有不同的类型。 It doesn't matter if these elements are deserialized in one or multiple lists in the "employeeAllocation" element/object.这些元素是在“employeeAllocation”元素/对象中的一个或多个列表中反序列化并不重要。

This is the XML snippet.这是 XML 片段。

    <ns3:EmployeeAllocationResponse
    xmlns:ns3="http://employeeallocation.intf.mb.ivu.de/"
    xmlns:ns2="http://employeeallocation.intf.mb.ivu.de/fault">
    <employeeAllocation>
        <allocatables
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns3:Duty">
            <startTime>2020-11-03T14:09:00.000</startTime>
            <endTime>2020-11-03T22:50:00.000</endTime>
            <shortName>64280S</shortName>
        </allocatables>
        <allocatables
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns3:Duty">
            <startTime>2020-11-03T14:09:00.000</startTime>
            <endTime>2020-11-03T22:50:00.000</endTime>
            <shortName>64280S</shortName>
        </allocatables>
    </employeeAllocation>
    <employeeAllocation>
        <allocatables
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns3:Absence">
            <typeAbbreviation>STAG</typeAbbreviation>
            <typeLongname>STAG-dagar</typeLongname>
            <startTime>2020-11-03T00:00:00.000</startTime>
            <endTime>2020-11-04T00:00:00.000</endTime>
            <type>STAG</type>
        </allocatables>
    </employeeAllocation>
    <employeeAllocation>
        <allocatables
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns3:Duty">
            <startTime>2020-11-03T21:00:00.000</startTime>
            <endTime>2020-11-04T06:45:00.000</endTime>
            <shortName>TPL1030</shortName>
            <rosterAbbreviation>DLT</rosterAbbreviation>
        </allocatables>
    </employeeAllocation>
</ns3:EmployeeAllocationResponse>

This is the "employeeAllocation" class这是“employeeAllocation”类

public class EmployeeAllocation
{
    [XmlElement("employee")]
    public Employee Employee { get; set; }

    [XmlElement("allocatables")]
    public List<Alloctable> Alloctables { get; set; }
}

This is the "alloctables" class这是“可分配的”类

[XmlType(Namespace = "http://employeeallocation.intf.mb.ivu.de/", TypeName = "Duty")]
public class Alloctable
{
    [XmlElement("startTime", Namespace = "")]
    public string StartTime { get; set; }
}

My problem is that I don't know how to add a new type of "alloctables" type to my list of Alloctables.我的问题是我不知道如何向我的可分配表列表中添加一种新的“可分配表”类型。 Now it can handle type="Duty" but crashed when trying to deserialize the other types.现在它可以处理 type="Duty" 但在尝试反序列化其他类型时崩溃。

I got it to work by serializing some test data and getting it to compare with you input xml data.我通过序列化一些测试数据并将其与您输入的 xml 数据进行比较来使其工作。 See code below :见下面的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        const string FILENAME1 = @"c:\temp\test1.xml";
        static void Main(string[] args)
        {
            string xml = File.ReadAllText(FILENAME);
            StringReader sReader = new StringReader(xml);
            XmlReader xReader = XmlReader.Create(sReader);
            XmlSerializer serializer = new XmlSerializer(typeof(EmployeeAllocationResponse));

            EmployeeAllocationResponse r = new EmployeeAllocationResponse()
            {
                Allocatables = new List<Allocatables>() {
                    new Duty(),
                    new Absence()
                }
            };
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Indent = true;
            XmlWriter writer = XmlWriter.Create(FILENAME1, settings);
            XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
            ns.Add("ns2", "http://employeeallocation.intf.mb.ivu.de/fault");
            ns.Add("ns3", "http://employeeallocation.intf.mb.ivu.de/");
            ns.Add("xsi", "http://www.w3.org/2001/XMLSchema-instance");
            serializer.Serialize(writer, r, ns);

            EmployeeAllocationResponse response = (EmployeeAllocationResponse)serializer.Deserialize(xReader);

        }
    }
    [XmlRoot(ElementName = "EmployeeAllocationResponse", Namespace = "http://employeeallocation.intf.mb.ivu.de/")]
    public class EmployeeAllocationResponse
    {
        [XmlArray(ElementName = "employeeAllocation", Namespace = "")]
        [XmlArrayItem(ElementName = "allocatables", Namespace = "")]
        public List<Allocatables> Allocatables { get; set; } 
    }
    [XmlRoot(ElementName = "allocatables", Namespace = "http://employeeallocation.intf.mb.ivu.de/")]
    [XmlInclude(typeof(Duty)), XmlInclude(typeof(Absence))]
    public class Allocatables
    {
        [XmlElement(ElementName = "startTime", Namespace = "")]
        public DateTime startTime { get; set; }
        [XmlElement(ElementName = "endTime", Namespace = "")]
        public DateTime endTime { get; set; }
    }
    [XmlRoot(ElementName = "Duty", Namespace = "http://employeeallocation.intf.mb.ivu.de/")]
    public class Duty : Allocatables
    {
        [XmlElement(ElementName = "shortName", Namespace = "")]
        public string shortName { get; set; }
        [XmlElement(ElementName = "rosterAbbreviation", Namespace = "")]
        public string rosterAbbreviation { get; set; }
    }
    [XmlRoot(ElementName = "Absence", Namespace = "http://employeeallocation.intf.mb.ivu.de/")]
    public class Absence : Allocatables
    {
        [XmlElement(ElementName = "typeAbbreviation", Namespace = "")]
        public string typeAbbreviation { get; set; }
        [XmlElement(ElementName = "typeLongname", Namespace = "")]
        public string typeLongname { get; set; }
        [XmlElement(ElementName = "type", Namespace = "")]
        public string type { get; set; }
    }
}

Thank you so much!非常感谢! The [IncludeXml] and [Root] was the key (pun intended ;D). [IncludeXml] 和 [Root] 是关键(双关语;D)。 Worked like a charm after adding these to the base class.将这些添加到基类后,效果非常好。 Thank you jdweng!谢谢jdweng!

[XmlRoot(ElementName = "allocatables", Namespace = "http://employeeallocation.intf.mb.ivu.de/")]
[XmlInclude(typeof(DutyAlloctable))]
[XmlInclude(typeof(AbsenceAlloctable))]
[XmlInclude(typeof(DayOffAlloctable))]
public class AlloctableBase 
{

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM