简体   繁体   中英

how to load XML to a generic list object in c#?

I have a "School" class that has nested "Student" class with "name" as a property for "Student".

public class school
{
    private List<student> mystudents;

    public class student
    {
        private string name;
    }
}

A School has many students and each student has a name.

I have an XML document:

 <school>
    <student>
        <name>John</name>
    </student>
    <student>
        <name>Jane</name>
    </student>
    <student>
        <name>Jack</name>
    </student>
 </school>

Lets say, I create a school object and would like to read this xml into school-object, how do I do it? I have written working-code for reading XML into an object, recursively copying values to all properties. I do not know how do I make this work for a List<T> ie generic list

Below is my code for reading an XML to generic object, recursively:

  /*----------------------------------------------------------------
    ' Template to read XML document into a Objects
    '-----------------------------------------------------------------*/
    public static T XmlToObject<T>(string fileName, T obj)
    {

        // read XML
        string xmlString = File.ReadAllText(fileName);
        XmlDocument xmlDocument = new XmlDocument();
        xmlDocument.LoadXml(xmlString);

        // read the root node
        XmlNode groupsListNode = xmlDocument.GetElementsByTagName(obj.GetType().Name).Item(0);

        // iterate through and copy values
        XmlNodeToListProperties(groupsListNode, obj);

        return obj;
    }

 public static void XmlNodeToProperties( XmlNode listNode, object obj)
    {
        //iterate through properties of object and copy from listNode
        foreach(var prop in obj.GetType().GetProperties())
        {
            if (listNode[prop.Name] != null)
            {
                if (listNode[prop.Name].ChildNodes.Count > 1) // has child-properties
                {
                    // call recursively
                    XmlNodeToProperties(listNode[prop.Name], prop.GetValue(obj, null));
                }
                else // no child properties
                {
                    // get proprty type
                    Type t = Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType;

                    // convert listNode.FirstChild.value to PropertyType
                    object safeValue = CustomConvert( listNode[prop.Name], t) ;
                    // store in object
                    prop.SetValue(obj, safeValue, null);
                }
            }

I did think of using serializers but the problem is it needs xmlElement("name") for each of the properties. Couple of my objects/classes come from an Third-party API, I dont have access to edit their class-file to insert `xmlElement("name"). Any suggestions on modifying/altering the above generic templates to accomodate generic-lists?

Why are you using GetElementsByTagName ? Are you aware that this actually gets all descendants of the given type?

If you want to "deserialize" a full object tree, you should start on the root and work your way through it. You'll need to ability to append new instances to the list/collection/array, or to object properties which are null in the obj instance.

You are speaking of 3rd-party objects. That's where doing that generically gets difficult; depending on the API you'll need to call some factory, methods on the parent, or constructors. If it is constructors, what do you do if it requires arguments, such as the owner/parent?

There needs to be a strict convention/definition as how this has to be done for it to work generically.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM