【问题标题】:Deserialize XML into object structure including dictionary将 XML 反序列化为对象结构,包括字典
【发布时间】:2018-09-17 18:39:56
【问题描述】:

我正在尝试将给定的 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 可以带有可变数量的属性。属性是数据库表的内容。

提前非常感谢

【问题讨论】:

  • 我会像 &lt;TableData Schema="dbo" Name="table2"&gt;&lt;RowData&gt;&lt;ColData Name="tab2col1"&gt;22&lt;/ColData&gt;&lt;ColData Name="tab2col2"&gt;someValue&lt;/ColData&gt; &lt;/RowData&gt;&lt;/TableData&gt; 那样重新构建我的 XML 以使其更具可扩展性,这也将有助于在您的代码中创建等效的映射结构
  • 如果您不控制 XML 文件的创建,那么您将不得不通过自定义序列化来实现您的需求 - stackoverflow.com/questions/17236823/… AND docs.microsoft.com/en-us/dotnet/standard/serialization/…

标签: c# xml dictionary deserialization


【解决方案1】:

试试 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; }
    }
}

【讨论】:

  • 你是个英雄。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-08-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-10
相关资源
最近更新 更多