将XML反序列化为包含字典的对象结构

时间:2018-09-17 18:39:56

标签: c# xml dictionary deserialization

我正在尝试将给定的XML文件反序列化为对象结构。

这是XML:

<StaticData>
  <Configuration>
    <SqlCmdParameters />
    <Tables>
      <Table Schema="dbo" Name="table1">
        <Columns>
          <Column Name="tab1col1" IsPrimaryKey="false" />
          <Column Name="tab1col2" IsPrimaryKey="false" />
        </Columns>
      </Table>
      <Table Schema="dbo" Name="table2">
        <Columns>
          <Column Name="tab2col1" IsPrimaryKey="false" />
          <Column Name="tab2col2" IsPrimaryKey="false" />
        </Columns>
      </Table>
    </Tables>
  </Configuration>
  <TableDataItems>
    <TableData Schema="dbo" Name="table1">
      <RowData tab1col1="11" tab1col2="text1" tab1col3="anotherText1" />
      <RowData tab1col1="12" tab1col2="text2" tab1col3="anotherText2"/>
      <RowData tab1col1="13" tab1col2="text3" tab1col3="anotherText3"/>

    </TableData>
    <TableData Schema="dbo" Name="table2">
      <RowData tab2col1="22" tab2col2="text1" />
      <RowData tab2col1="23" tab2col2="text1" />
      <RowData tab2col1="24" tab2col2="text1" />
    </TableData>
  </TableDataItems>
</StaticData>

我要填写的课程是:

    [XmlRoot("StaticData")]
public class StaticData
{
    [XmlElement("Configuration")]
    public Configuration Configuration { get; set; }

    [XmlElement("TableDataItems")]
    public TableDataItems TableDataItems { get; set; }
}

public class Configuration
{
    [XmlElement("Tables")]
    public List<Table> Tables { get; set; }

    [XmlElement("SqlCmdParameters")]
    public List<SqlCommandParameter> SqlCommandParameters { get; set; }
}

public class TableDataItems
{
    [XmlElement("TableData")]
    public List<Table> TableDatas { get; set; }
}

public class Table
{
    [XmlAttribute("Name")]
    public string TableName { get; set; }

    [XmlAttribute("Schema")]
    public string SchemaName { get; set; }

    [XmlElement("Columns")]
    public List<Column> Columns { get; set; }

    [XmlElement("RowData")]
    public List<Row> Rows { get; set; }

    public Table()
    {
        Columns = new List<Column>();
        Rows = new List<Row>();
    }
}

public class Column
{
    [XmlAttribute("Name")]
    public string Name { get; set; }

    [XmlAttribute("IsPrimaryKey")]
    public bool IsPrimaryKey { get; set; }
}

public class Row
{
    public Row()
    { 
        RowData = new Dictionary<string, string>();
    }
    ???What Attribute should I put here???
    public Dictionary<string, string> RowData { get; set; }
}

所以,一切正常,直到我到达应该将所有属性填充到字典中的位置为止。

到目前为止,这是我反序列化XML的方式:

public void CreateObjectStructureFromXml()
    {
        using (TextReader textReader = new StringReader(XmlDocument.ToString()))
        {
            XmlSerializer serializer = new XmlSerializer(typeof(StaticData));
            StaticData = (StaticData) serializer.Deserialize(textReader);
        }
    }

我一旦获得Row元素,就会得到一个异常。

有人可以指出我的错误之处或应该怎么做吗? XML RowData可以带有可变数量的属性。这些属性是数据库表的内容。

非常感谢

1 个答案:

答案 0 :(得分:0)

尝试xml linq:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            XDocument doc = XDocument.Load(FILENAME);

            Table.tables = doc.Descendants("Table").Select(x => new Table() {
                SchemaName = (string)x.Attribute("Schema"),
                TableName = (string)x.Attribute("Name"),
                Columns = x.Descendants("Column").Select(y => new Column()
{
                    Name = (string)y.Attribute("Name"),
                    IsPrimaryKey = (Boolean)y.Attribute("IsPrimaryKey")
                }).ToList()
            }).ToList();

            Dictionary<string, XElement> tableData = doc.Descendants("TableData")
                .GroupBy(x => (string)x.Attribute("Name"), y => y)
                .ToDictionary(x => x.Key, y => y.FirstOrDefault());

            foreach(Table table in Table.tables)
            {
                XElement xTable = tableData[table.TableName];
                table.SchemaName = (string)xTable.Attribute("Schema");
                table.Rows = xTable.Elements("RowData").Select(x => new Row() {
                    RowData = x.Attributes()
                    .GroupBy(y => y.Name.LocalName, z => (string)z)
                    .ToDictionary(y => y.Key, z => z.FirstOrDefault())
                }).ToList();
            }

        }
    }
    public class Table
    {
        public static List<Table> tables = new List<Table>();
        public string TableName { get; set; }

        public string SchemaName { get; set; }

        public List<Column> Columns { get; set; }

        public List<Row> Rows { get; set; }

        public Table()
        {
            Columns = new List<Column>();
            Rows = new List<Row>();
        }
    }
    public class Column
    {
        public string Name { get; set; }

        public bool IsPrimaryKey { get; set; }
    }

    public class Row
    {
        public Dictionary<string, string> RowData { get; set; }
    }
}