0

What is the best object model to serialize and deserialize an XML like this :

<root>
    <header>
        <elementA>Example</elementA>
        <elementB>Test</elementB>
    </header>
    <content>
        <elementC>foo</elementC>
        <variousTypeA>
            <itemA>Test</itemA>
            <itemB>Test</itemB>
            <itemC>Test</itemC>
        </variousTypeA>
    </content>
</root>

My problem is to update the variousTypeA with an other like this :

<root>
    <header>
        <elementA>Example</elementA>
        <elementB>Test</elementB>
    </header>
    <content>
        <elementC>foo</elementC>
        <variousTypeB>
            <itemZ>Test</itemZ>
            <itemY>Test</itemY>
            <itemX>Test</itemX>
        </variousTypeB>
    </content>
</root>

What is the best option to generate XML with

XmlSerializer xmlSerializer = new XmlSerializer(typeof(variousTypeA));

and

XmlSerializer xmlSerializer = new XmlSerializer(typeof(variousTypeB));

but without repeat the common elements...

The schema must to be usable with the C# XmlSerializer class. Do you have an object model to propose ?

  • 1
    Do **you** have any object models to propose? :) – Roman Nov 24 '16 at 17:08
  • Do you have a DTD or XML|RNG schema describing the documents? – choroba Nov 24 '16 at 17:08
  • For generic advice see [Generate C# class from XML](https://stackoverflow.com/questions/4203540/generate-c-sharp-class-from-xml). If you have difficulties with the standard solutions there, feel free to ask a more specific question. – dbc Nov 24 '16 at 17:21
  • I've updated my question ... Is it clearer? I'm looking for the best class organization to have a simple and clean code... – le8ejumeau Nov 24 '16 at 21:58

1 Answers1

0

One solution would be to create a class hierarchy corresponding to the various possible <content> elements, like so:

public abstract class ContentBase
{
    public string elementC { get; set; }
}

public class ContentA : ContentBase
{
    public VariousTypeA variousTypeA { get; set; }
}

public class ContentB : ContentBase
{
    public VariousTypeB variousTypeB { get; set; }
}

Then, for the POCO corresponding to the <root> element, create a class hierarchy where the base type specifies common properties and the derived type is a generic that indicates the specific type of Content object, constrained to be of type ContentBase:

public abstract class RootBase
{
    public Header header { get; set; }

    [XmlIgnore]
    // The following provides get-only access to the specific content of this root
    public abstract ContentBase BasicContent { get; }
}

public class Header
{
    public string elementA { get; set; }
    public string elementB { get; set; }
}

[XmlRoot(ElementName = "root")]
public class Root<TContent> : RootBase 
    where TContent : ContentBase
{
    public TContent content { get; set; }

    public override ContentBase BasicContent { get { return content; } }
}

Then use it like:

var rootA = (Root<ContentA>)new XmlSerializer(typeof(Root<ContentA>)).Deserialize(new StringReader(xmlStringA));

Or

var rootB = (Root<ContentB>)new XmlSerializer(typeof(Root<ContentB>)).Deserialize(new StringReader(xmlStringB));

This design allows for code relating to the common elements of <root> and <content> to be shared.

Sample fiddle.

dbc
  • 104,963
  • 20
  • 228
  • 340
  • Oh wahou !! It's exactly I'm searching... I'll implement it soon and I come back here to say you the result... – le8ejumeau Dec 01 '16 at 09:19