Search code examples
c#.netxml-deserialization

Deserialize Xml Properties depending from attribute value


I try to deserialize this xml:

<AccountInfo ID="accid1" Currency="EUR">
  <AccountNumber international="false">10000</AccountNumber>
  <AccountNumber international="true">DE10000</AccountNumber>
  <BankCode international="false">22222</BankCode>
  <BankCode international="true">BC22222</BankCode>
  <AccountHolder>Some Dude</AccountHolder>
</AccountInfo>

into following class:

public class AccountInfo 
{
  public int ID {get; set;}
  public string Currency {get; set;}
  public long AccountNumber {get; set;} //this should be filled if international == false
  public string BankCode {get; set;}
  public long AccountNumberInternational {get; set;} //this should be filled if internation == true
  public string BankCodeInternational {get; set;}
  public string AccountHolder {get; set;}
}

but i stuck in the part how to tell the Deserializer (System.Xml.Serialization, .NET 4.6.1) to fill the Properties AccountNumber/BankCode of the class depending on the Attribute "international" from AccountNumber/BankCode from the xml.

I tried using this "Serialisation" classes so far:

    [XmlRoot("AccountInfo")]
    public class AccountInfo
    {
        [XmlAttribute]
        public int ID { get; set; }

        [XmlAttribute]
        public string Currency { get; set; }

        [XmlElement]
        public BankAccount BankAccount { get; set; }

        public string AccountHolder { get; set; }
    }

    public class BankAccount
    {
        public long AccountNumber { get; set; }

        public int BankCode { get; set; }
    }

but this don't even lead near to the structure that i need.

Completely wrong xml

How do i need to declare the classes for Serialisation?


Solution

  • XmlSerializer is designed to deserialize data into a DTO model that is basically the same shape as the XML, so something like:

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Xml.Serialization;
    
    static class Program
    {
        static void Main()
        {
            var xml = @"<AccountInfo ID=""accid1"" Currency=""EUR"">
      <AccountNumber international=""false"">10000</AccountNumber>
      <AccountNumber international=""true"">DE10000</AccountNumber>
      <BankCode international=""false"">22222</BankCode>
      <BankCode international=""true"">BC22222</BankCode>
      <AccountHolder>Some Dude</AccountHolder>
    </AccountInfo>";
            var ser = new XmlSerializer(typeof(AccountInfo));
            var obj = ser.Deserialize(new StringReader(xml));
    
            // ...
        }
    }
    
    public class AccountInfo
    {
        [XmlElement]
        public List<BankAccount> AccountNumber { get; } = new List<BankAccount>();
        [XmlElement]
        public List<BankAccount> BankCode { get; } = new List<BankAccount>();
    
        public string AccountHolder { get; set; }
    
        [XmlAttribute("ID")]
        public string Id {get;set;}
    
        [XmlAttribute]
        public string Currency {get;set;}
    }
    public class BankAccount
    {
        [XmlAttribute("international")]
        public bool International { get; set; }
        [XmlText]
        public string Number { get; set; }
    }
    

    Which values from that you want to select and push into your domain model should be done afterwards, by you - for example by only selecting the international or non-international items from the lists.