0

I have a xml file that I want to map to a C# class

The xml looks like this:

<root>
    <table>
       <fields>
           <field name="createdby">Thomas</field>
           <field name="id">123</field>
           <field name="Title">New Article</field>
       </fields>
    </table>
</root>

And I have created some classes to map this, not sure if this is the shortest way to do that:

Root:

    [XmlRoot(ElementName = "root")]
    public class Root
    {
        [XmlElement(ElementName = "table")]
        public Table Table { get; set; }

    }

Table:

    [XmlRoot(ElementName = "table")]
    public class Table
    {
        [XmlElement(ElementName = "fields")]
        public Fields Fields { get; set; }
        //[XmlAttribute(AttributeName = "name")]
        //public string Name { get; set; }
        //[XmlElement(ElementName = "table")]
        //public List<Table> TableList { get; set; }
        }

Fields:

    [XmlRoot(ElementName = "fields")]
    public class Fields
    {
        [XmlElement(ElementName = "field")]
        public List<Field> Field { get; set; }
    }

Field:

    [XmlRoot(ElementName = "field")]
    public class Field
    {
        //Would like to the the createdby name here "Thomas"
        [XmlAttribute(AttributeName="createdby")]
        public string Name { get; set; }
        [XmlAttribute(AttributeName="id")]
        public int Id { get; set; }
        [XmlAttribute(AttributeName="title")]
        public string Title { get; set; }
    }

is this the right approach ??

Hope someone can help and maybe find a clean way.. :P

The goal is to have a class called

public class Article
    {
        public string Name { get; set; }
        public string Id { get; set; }
        public string CreatedBy { get; set; }

        public string Content { get; set; }
    }

Where I can map data values from the xml file to this. Something like this.

Article article = new Article();
Article.CreatedBy = result.Table.Fields.Field.Createdby
Thomashdk
  • 13
  • 8
  • Possible duplicate of [Generate C# class from XML](https://stackoverflow.com/questions/4203540/generate-c-sharp-class-from-xml) – dymanoid Aug 09 '19 at 11:26
  • I don't think it's clear have to map by Attribute name in that answer. It's not the element name I will fetch from here, but the attribute value "createdby" in this case. – Thomashdk Aug 09 '19 at 11:32
  • Using Serialization methods you have to write your own code to reformat the class data to a flat table (one class) after de-serializing. The xml has lots of levels of hierarchy. I find it is easier to use Xml Linq (XDocument) to parse xml to one class than to do two steps of deserializing and then parsing the classes to get a flat one class table. – jdweng Aug 09 '19 at 12:02
  • @jdweng Do you have a ex. somewhere ? or a link ? – Thomashdk Aug 09 '19 at 13:03
  • See following posting : https://stackoverflow.com/questions/57355884/how-to-keep-parent-element-reference-while-parsing-list-of-children-in-xml-to-ob/57356298#57356298 – jdweng Aug 09 '19 at 13:11

1 Answers1

0

as i understand you need a proper class to serialize to. here as example:

public partial class root
{
    public Table table {get;set;}
}
public partial class Table
{
    public Fields fields {get;set;}
}

public partial class Fields
{
    public Field field {get;set;}
}
public partial class Field
{
    [System.Xml.Serialization.XmlAttributeAttribute()]
    public string name {get;set;}
    [System.Xml.Serialization.XmlTextAttribute()]
    public string Value {get;set;}
}

and code (there are different approaches) i made up as example:

string xml = "<root><table><fields><field name=\"createdBy\">Thomas</field></fields></table></root>";
    XDocument x = XDocument.Parse(xml, LoadOptions.PreserveWhitespace);
    XmlSerializer ser = new XmlSerializer(typeof(root));
    XmlReader reader2 = x.CreateReader();
    root res = (root)ser.Deserialize(reader2);
    var author = res.table.fields.field;
    Console.WriteLine($"{author.name} : {author.Value}");

EDITED: you can add another filed to class (i added to root):

public partial class root
{
    public Table table { get; set; }
    [XmlIgnoreAttribute]
    public string Author => table.fields.field.name + " " + table.fields.field.Value;
}

and now you can do what you want:

res.Author
Power Mouse
  • 727
  • 6
  • 16
  • is it not possible to do something like this? public partial class Fields { [System.Xml.Serialization.XmlAttributeAttribute("createdby")] public string Createdby {get;set;} [System.Xml.Serialization.XmlAttributeAttribute("id")] public int Id {get;set;} } – Thomashdk Aug 09 '19 at 13:01
  • possible to create extra class property which will populate combined values when class is populated – Power Mouse Aug 09 '19 at 13:04
  • I have edit my question to may specify more want i'm trying to do. I would like to be able to specify what values in ex. root/table/fields and then the one with attribute name value "createdby" – Thomashdk Aug 09 '19 at 13:26
  • i gave you answer. i edited my answer. as example i used name Author , you will use createdby – Power Mouse Aug 09 '19 at 13:47