Click here to Skip to main content
14,981,841 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
C#
I am trying to generate an xml by serializing and facing some issues. There is a part of xml which is dynamic. the section "person" is dynamic i.e the sub sections
 person can increase or decrease. I am able to serialie the class with static value( with single person name and age) but when getting multiple 
values then I am not able to handle that.All the values are fetched from database and every name and age is store as a distinct row in database.So if I have 2 names and age then it will be stored
as 2 distinct rows in database. I tried to create a loop(on basis of number of rows) but not able understand how to incorporate the dynamic section to rest of xml
part.

Can someone help on this?

--------------- desired xml output--------------------------------------

   
<details>
 <description>Some description</description>
 <hobby> Anything</hobby>

<person>
   <name>Dann</name>
   <age>21</age>
</person>
<person>
   <name>Scott</name>
   <age>23</name>
</person>


</details>

--------------------------------------------------CODE -----------------------------------------

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Configuration;
using System.Data.SqlClient;
using System.Data;
using System.Xml.Serialization;

namespace xmltest
{
    public class Program
    {
        public class xmlserial
        {

            [XmlElement("details")]
            public string details { get; set; }
            [XmlElement("description")]
            public string description { get; set; }
            [XmlElement("hobby")]
            public string hobby { get; set; }

            [XmlElement("person")]
            public string person { get; set; }
            [XmlElement("name")]
            public string name { get; set; }
            [XmlElement("age")]
            public int age { get; set; }

            public xmlserial()
            {
            }

        }
        static void Main(string[] args)
        {

            string conStr = ConfigurationManager.ConnectionStrings["Test"].ToString();
            DataSet abc = new DataSet();
            abc = test_DS(conStr);

            List<xmlserial> AddressList = new List<xmlserial>();
            xmlserial y = new xmlserial();
            foreach (DataTable dt in abc.Tables)
            {

                y.details = "hello";
                y.description = "description";
                y.hobby = "hobby";
                y.person = "person";
                foreach (DataRow dr in dt.Rows)
                {

                    y.name = dr["NAME"].ToString();
                    y.age =(int) dr["age"];

                }
                AddressList.Add(y);
            }
            serialize(AddressList);

        }
        public static void serialize(List<xmlserial> list)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(List<xmlserial>));
            serializer.Serialize(Console.Out, list);
            Console.WriteLine();
            Console.ReadLine();

        }

        public static DataSet test_DS(string conStr)
        {
            try
            {
                using (SqlConnection SqlConn = new SqlConnection(conStr))
                {

                    SqlConn.Open();

                    using (SqlCommand cmd = new SqlCommand())
                    {
                        cmd.Connection = SqlConn;

                        cmd.CommandType = CommandType.StoredProcedure;
                        cmd.CommandText = "dbo.test_sp";                      

                        using (SqlDataAdapter da = new SqlDataAdapter(cmd))
                        {                      
                            DataSet dataset = new DataSet();
                            da.Fill(dataset);

                            return dataset;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                //Catch the exception

            }
            return null;
        }

    }
}

--------------------------------------------------------------------------------SQL  table and Procedure ---------------------------------

create table persondetails(name varchar(20),age int)
insert into persondetails(name,age)
select 'Dann',21
union all
select 'Scott',23
union all
Select 'Allen',24



create proc test_sp
as
 begin
   select distinct * from persondetails
 end
Posted

1 solution

First of all, I would recommend using Data Contract for serialization: Using Data Contracts[^];
see also: DataContractSerializer Class (System.Runtime.Serialization)[^].

This is the only fully non-intrusive to serialize: you don't have to implement any special interfaces, nor you need to inherit your data types from any special types. You simply add some attributes to the types and members, almost exclusively [DataContract] and [DataMember]. This way, you simply define the contract (data members may have any access modifiers, don't have to be public, non-contact members can be added or removed as you develop without affecting contract and persistence) and create some object or object graph, which does not even need to be a tree, can have circular referenced. This graph is fully serialized and can be restored in memory the way it was before.

Now, how it looks with "increase and decrease"? The idea is: arrays and all major collections are already supported. Let me show one most important pattern of using dynamically resized composition of child objects:

C#
using System.Collections.Generic;

//...

[DataContract(/* ... */)] // most usually, you define namespace (URL)
class Person { /* ... */ }

[DataContract(/* ... */)] // say, the same namespace
class MyParent {
  
   [DataMember(Name = "people"]
   List<Person> people = new List<Person>(); // private! always exists, never null
   // it was the interface for serializer, now the programming interface to the same thing:
   List<Person> People { get { return people; } }

   // now, you can use People to add or remove instances of Person 
   // to/from the collection

   // of course, you could have only one List member
   // for this purpose, but my pattern isolate programming
   // and persistence interface (contract), to make sure
   // that no one will replace the object reference (isolation)

   // ...

}

This is so simple for non-polymorphic sets of children. Polymorphic is harder. You can make People an abstract class and derive concrete classes; instances of those terminal classes will be added to People, that is, the runtime types of objects placed in People cannot be of the type Person, they all will be some derived types. But how the serializer knows that some XML node gives the name of a type from a polymorphic type set? This is how: all derived types to be used in a set should be mentioned in a set of the attribute [KnownType], which should be applied to your base class People:
KnownTypeAttribute Class (System.Runtime.Serialization)[^].

Perhaps my explanation of polymorphic sets was not detailed enough, but you did not ask about polymorphic sets; however, sooner or later you will face them, too, if you really do OOP. :-)

—SA
   
v4

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)




CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900