'XmlSerializer - Combining multiple elements into a list which all have the same signature but different tag names

I'm still pretty fresh to C# and XML so excuse me if I use the wrong terminology.

I'm trying to serialize an XML string into a class I'm building. The problem is, one of the elements contains a "list" of elements that all have the same structure, but they each have a different tag name...like so:

<Results>
  <factors>
    <factor1 code="012">Some text</factor1>
    <factor2 code="123">Some text</factor2>
    <factor3 code="234">Some text</factor3>
    <factor4 code="345">Some text</factor4>
    <factor5 code="456">Some text</factor5>
  </factors>
</Results>

I've built a class like this:

public class Factor
{
  [XmlAttribute("code")]
  public string Code { get; set; }
  [XmlText]
  public string Text { get; set; }
}

public class Factors
{
  [XmlElement("factor1")]
  public Factor Factor1 { get; set; }

  [XmlElement("factor2")]
  public Factor Factor2 { get; set; }

  [XmlElement("factor3")]
  public Factor Factor3 { get; set; }

  [XmlElement("factor4")]
  public Factor Factor4 { get; set; }

  [XmlElement("factor5")]
  public Factor Factor5 { get; set; }
}

[XmlRoot("Results")]
public class Results
{
  [XmlElement("factors")]
  public Factors Factors { get; set; }
}

Since in this case, Factor1-5 all have the same "shape", is there a way for me to read these into a list instead?

This isn't something I absolutely need to figure out, but I was curious to see if there was a simple solution for it.



Solution 1:[1]

Try this on for size. If you don't need to re-serialize the objects, this will deserialize your example XML in (note the added ElementName on Factor if you need to know what the actual element name was. Otherwise, discard it from the class and code).

public class Factor
{
    public string ElementName { get; set; }
    public string Code { get; set; }
    public string Text { get; set; }
}

[XmlRoot("Results")]
public class Results : IXmlSerializable
{
    public Factor[] Factors { get; set; }

    public XmlSchema GetSchema() => null;

    public void ReadXml(XmlReader reader) => this.Factors = XDocument
        .Load(reader.ReadSubtree())
        .Descendants("factors")
        .Descendants()
        .Select(factorElement => new Factor
        {
            ElementName = factorElement.Name.ToString(),
            Code = (string)factorElement.Attribute("code"),
            Text = factorElement.Value
        })
        .ToArray();

    public void WriteXml(XmlWriter writer) => throw new NotSupportedException();
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Jesse C. Slicer