动态xml序列化问题 [英] Issue with dynamic xml serialization

查看:74
本文介绍了动态xml序列化问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图通过序列化和面临一些问题来生成xml。  是xml的一部分,其中   dynamic 。部分  person    dynamic 即子部分
人可以增加或减少。我能够使用 static 序列 span>(单人姓名和年龄)但获得多个
值时,我无法处理。所有值都被提取来自数据库,每个名称和年龄 存储为 a 数据库中的不同行。如果 我有 2 名称和年龄然后它将被存储
2 不同的行数据库中的code-keyword>。我尝试创建一个循环(基于行数)但不能理解如何将动态部分合并到xml
部分的其余部分。

有人可以帮助这个吗?

---------------所需的xml输出------------------------ --------------


< details>
< description>部分说明< / description >
<业余爱好>任何< / 业余爱好 >

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


< / 详细信息 >

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

使用系统;
使用 System.Collections.Generic;
使用 System.Linq;
使用 System.Text;
使用 System.Threading.Tasks;
使用 System.Configuration;
使用 System.Data.SqlClient;
使用 System.Data;
使用 System.Xml.Serialization;

命名空间 xmltest
{
public class 计划
{
public class xmlserial
{

[XmlElement( details)]
public string 详细信息{ get ; set ; }
[XmlElement( description)]
public string description { get ; set ; }
[XmlElement( 业余爱好)]
public string 业余爱好{ get ; set ; }

[XmlElement( person)]
< span class =code-keyword> 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 [ 测试]。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 = 业余爱好;
y.person = person;
foreach (DataRow dr in dt.Rows)
{

y.name = dr [ NAME]。ToString();
y.age =( int )dr [ 年龄];

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

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

}

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

SqlConn.Open();

使用(SqlCommand cmd = new SqlCommand())
{
cmd.Connection = SqlConn;

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

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

return 数据集;
}
}
}
}
catch (例外情况)
{
// 抓住异常

}
return null ;
}

}
}

----------------------- -------------------------------------------------- ------- SQL表和程序---------------------------------

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



create proc test_sp
as
begin
se lect distinct * 来自 persondetails
end

解决方案

< blockquote>首先,我建议使用Data Contract进行序列化:使用数据合同 [ ^ ];

另见: DataContractSerializer类(System.Runtime.Serialization) [ ^ ]。



这是唯一完全非侵入式序列化:您不必实现任何特殊接口,也不需要从任何特殊接口继承您的数据类型类型。您只需向类型和成员添加一些属性,几乎完全是 [DataContract] [DataMember] 。这样,您只需定义合同(数据成员可以具有任何访问修饰符,不必是公共的,可以在开发时添加或删除非联系成员而不影响合同和持久性)并创建一些对象或对象图,甚至不需要是树,可以循环引用。这个图是完全序列化的,可以像以前一样在内存中恢复。



现在,它看起来如何增加和减少?这个想法是:已经支持数组和所有主要的集合。让我展示使用动态调整大小的组合子对象的一个​​最重要的模式:



 使用 System.Collections.Generic; 

// ...

[ DataContract( / * ... * / )] / / 通常,您定义名称空间(URL)
class 人{< span class =code-comment> / * ... * / }

[DataContract( / * ... * / )] // < span class =code-comment>例如,相同的命名空间
class MyParent {

[DataMember( Name = people]
列表< Person> people = new List< Person>(); // private!always exists,never null < /秒pan>
// 它是序列化程序的接口,现在是同一个程序的编程接口:
List< Person>人{获取 {返回人; }

// 现在,您可以使用People添加或删除Person的实例
// 来自集合

// 当然,您只能有一个List成员
// 为此目的,但我的模式隔离了编程
// 和持久性接口(合同),以确保
// 没有人会替换对象引用(隔离)

// ...

}



对于非多态的子集,这非常简单。多态更难。你可以使 People 一个抽象类并派生出具体的类;这些终端类的实例将被添加到 People ,即放置在 People中的对象的运行时类型 不能是 Person 类型,它们都是一些派生类型。但是,序列化程序如何知道某些XML节点从多态类型集中提供了类型的名称?这是这样的:在一组属性 [KnownType] 中应该提到要在集合中使用的所有派生类型,它应该应用于你的基类

KnownTypeAttribute类(System.Runtime.Serialization) [ ^ ]。



也许是我的多态集的解释不够详细,但你没有问过多态集;但是,如果你真的做OOP,迟早你也会面对它们。 :-)



-SA


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

解决方案

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:

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


这篇关于动态xml序列化问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆