简体   繁体   中英

How to deserialize two different XML types in to one class

I have two different XML documents. Their structure is almost identical, but they have some different elements.

I would like to deserialize the incoming documents in to one class which is a superset of both classes. There is no need to ever serialize the class, I only need to deserialize the documents.

The XML document types have a different root element, lets say the root of the first is <CLASSA> and the other is <CLASSB> . I am looking for something like this, where both <CLASSA> and <CLASSB> xml documents are mapped to ClassAandB :

[XmlRoot(ElementName="CLASSA,CLASSB")]
public class ClassAandB {
    [XmlElement(ElementName="syntaxid")]
    public Syntaxid Syntaxid{ get; set; }
    [XmlElement(ElementName="email")]
    public Email Email { get; set; }
    [XmlElement(ElementName="envelope")]
    public Envelope Envelope { get; set; }
    [XmlElement(ElementName="header")]
    public Header Header { get; set; }
}

I can then find out which of the two types it is by reading the Syntaxid property. This helps me because a lot of the processing is the same for both types. Any suggestions how to do this?

I suggest you to remove XmlRoot attribute and use:

var doc = new XmlDocument();
doc.Load("file.xml");
XmlElement root = xmlDoc.DocumentElement;
var serializer = new XmlSerializer(typeof(ClassAandB), new XmlRootAttribute(root.ToString()));

Since the xml root element name might depend on the content of the xml document, you'll have to configure the XmlSerializer at runtime with this xml root element name to be used.
In this case, there's no need anymore to apply an XmlRootAttribute .

This can be done via the constructor overload accepting an XmlRootAttribute argument, via which you pass the root element name.

public XmlSerializer (Type type, System.Xml.Serialization.XmlRootAttribute root);

You might know the root element name in front eg. depending on the source of the xml document, or you might discover it at runtime from the xml document itself.

The following from the example below shows how the xml root element name gets set.

String rootName = "CLASSA"; // "CLASSB"
var serializer = new XmlSerializer(typeof(ClassAandB), new XmlRootAttribute(rootName));

An simplified example using an XmlReader as source and retrieving the root xml element name from the content.

public class ClassAandB 
{
    [XmlElement(ElementName="syntaxid")]
    public String Syntaxid{ get; set; }

    [XmlElement(ElementName="email")]
    public String Email { get; set; }

    [XmlElement(ElementName="header")]
    public String Header { get; set; }
}

var classA = Deserialize(XmlReader.Create(
    new StringReader("<CLASSA><syntaxid>A</syntaxid></CLASSA>"))
    );
Console.WriteLine(classA.Syntaxid); // A

var classB = Deserialize(
    XmlReader.Create(new StringReader("<CLASSB><syntaxid>B</syntaxid></CLASSB>"))
    );
Console.WriteLine(classB.Syntaxid); // B

public static ClassAandB Deserialize(XmlReader reader)
{
    reader.MoveToContent();
    string rootName = reader.Name;
    var serializer  = new XmlSerializer(typeof(ClassAandB), 
        new XmlRootAttribute(rootName)
        );
    var deserialized = serializer.Deserialize(reader) as ClassAandB;
    return deserialized;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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