2

Given an XML structure that countains both attributes and element values, how do I construct my C# classes using the System.Xml.Serialization attributes?

My XML looks like this:

<Accounts>
    <Number credit="1000">100987654321</Number>
    <Number credit="0"   >100987654322</Number>
<Accounts>

I have been trying with this class structure, but it does not accept the XML.

public class Customer
{
    [DataMember, XmlArrayItem(ElementName = "Accounts")]
    public AccountNumber[] AccountNumbers;
}

public class AccountNumber
{
        [DataMember, XmlElement(ElementName = "Number")]
        public string AccountNumber;

        [DataMember, XmlAttribute(AttributeName = "credit")]
        public int Credit;
}

The trick is to NOT have an array of numbers nested in the "Number" element. We often see this construct in eg. html tags, where you have a tag with some styling perhaps, and the the actual value in between the

"... height=12px> value </..."

1 Answers1

5

The AccountNumber class can be defined as follows:

public class AccountNumber
{
    [XmlText]
    public string Number { get; set; }

    [XmlAttribute(AttributeName = "credit")]
    public int Credit { get; set; }
}

This results in the attribute and element text to be deserialized correctly.

PS. I had to change the AccountNumber to Number because it would otherwise not compile, and the Credit property from DateTime to int as the values of the attribute clearly aren't dates/times.

You probably have to fix your Customer class too, I used the following to test with:

[XmlRoot("Accounts")]
public class Accounts
{
    [XmlElement(ElementName = "Number")]
    public AccountNumber[] AccountNumbers;
}

And the test "program" itself:

static void Main(string[] args)
{
    string str = @"<Accounts><Number credit=""1000"">100987654321</Number><Number credit=""0"">100987654322</Number></Accounts>";

    using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(str)))
    {
        XmlSerializer ser = new XmlSerializer(typeof(Accounts));
        var result = (Accounts)ser.Deserialize(stream);
    }
}
C.Evenhuis
  • 25,996
  • 2
  • 58
  • 72
  • Thank you, I used your solution and it works perfectly - don't know how that one has slipped my attention ;)You are absolutely right about the Credit type, I've changed it in the post. Thanks again! – Andreas R. Munch Jul 19 '17 at 07:10