Search code examples
c#.netxmlxmlserializer

Deserialize into object from not nested xml


Imaging an XML-file like this:

<?xml version="1.0" encoding="UTF-16"?>
<treffer>
    <prod_internid>123456789</prod_internid>
    <md_nr>123123</md_nr>
    <md_mart_id>4</md_mart_id>
    <md_mtyp_nr>9876</md_mtyp_nr>
    <mra_th>
        <ie_th_pth>-1</ie_th_pth>
        <ie_th_ea_bez>Fehler: Keine Angabe</ie_th_ea_bez>
    </mra_th>
</treffer>

As you can see, there are three tags with <md_XY></md_XY>. I want to deserialize them into an object that looks like this:

public class DeMedienXmlDto
{
    [XmlElement("md_nr")]
    public int MedienNr { get; set; }

    [XmlElement("md_mart_id")]
    public int MedienArtId { get; set; }

    [XmlElement("md_mtyp_nr")]
    public string MedienTypId { get; set; }
}

But this should be a property of the whole deserialized object:

[XmlRoot("treffer")]
public class DeAnalyseArtikelXmlDto
{
    [XmlElement("prod_internid")]
    public long ArtikelId { get; set; }

    [XmlElement("treffer")]
    public DeMedienXmlDto Medium { get; set; }

    [XmlElement("mra_th")]
    public List<DeThemenXmlDto> Themen { get; set; }
}

I've tried annotating the Medium property with [XmlElement("treffer")] since the tags are childs of <treffer> but that didn't work...

Deserializing the <mra_th>...</mra_th> works since I can annotate the list with the grouped tag but I don't have such a tag for <md...>.

  • How can I achieve this?

My xml deserializer looks like this:

public class XmlDeserializer : IXmlDeserializer
{
    public T Deserialize<T>(string xmlFilename)
    {
        var returnObject = default(T);
        if (string.IsNullOrEmpty(xmlFilename)) return default(T);

        try
        {
            var xmlStream = new StreamReader(xmlFilename);
            var serializer = new XmlSerializer(typeof(T));
            returnObject = (T)serializer.Deserialize(xmlStream);
        }
        catch (Exception exception) {
            LogHelper.LogError($"Das XML-File {xmlFilename} konnte nicht deserialisiert werden: {exception.Message}");
            throw;
        }
        return returnObject;
    }
}

Thanks in advance

Edit (to clarify):

I want the following tags deserialized into an object of type DeMedienXmlDto:

  • <md_nr>
  • <md_mart_id>
  • <md_mtyp_nr>

Solution

  • This is not how XmlSerializer works. The class structure must correspond to structure of the XML in order to work automatically.

    This:

    [XmlElement("treffer")]
    public DeMedienXmlDto Medium { get; set; }
    

    doesn't work, because there is no nested <treffer> element. The XmlElementAttribute cannot denote the parent (surrounding) element.

    The are two options how to solve your situation:

    1. Use a separate set of classes for deserialization, and a separate set representing your DTO objects. You'd then need to create a mapping.
    2. Implement IXmlSerializable on DeAnalyseArtikelXmlDto and parse the inner XML yourself.