【问题标题】:Reading XML with records with different columns in same records array读取具有相同记录数组中不同列的记录的 XML
【发布时间】:2017-01-03 08:01:36
【问题描述】:

我需要在 C# 中解析 XML 响应并在 SQL 中加载。 简而言之,我知道如何使用 XMLSerializer 来解析 xml,所以这不是我想要的。我担心的是我从 Web 请求中收到的 XML 结构。下面是 xml 的子集,我从 xml 收到的

<apiXML>
<recordList>
<record id="31" >
    <administration_name>admin1</administration_name>
    <creator>Leekha, Mohit</creator>
    <object_category>painting</object_category>
    <object_number>1243</object_number>
    <id>31</id>
    <reproduction.reference>2458.jpg</reproduction.reference>
    <title lang="nl-NL" invariant="false">The Title1</title>
    <title lang="nl-NL" invariant="false">The Title</title>
    <title lang="nl-NL" invariant="false">Different Title</title>
</record>
<record id="32" >
    <administration_name>admin1</administration_name>
    <creator>Leekha, Mohit</creator>
    <object_category>painting</object_category>
    <object_number>AL1111</object_number>
    <id>32</id>
    <reproduction.reference>AL1111.jpg</reproduction.reference>
    <title lang="nl-NL" invariant="false">Health</title>
</record>
<record id="34" >
    <administration_name>admin2</administration_name>
    <creator>Leekha,Mohit</creator>
    <creator>System</creator>
    <object_category>earthenware</object_category>
    <object_category>ABC</object_category>
    <object_category>Remote</object_category>
    <object_number>Z.567 & X-124</object_number>
    <id>34</id>
    <reproduction.reference>Z.567 & X-124(1).jpg</reproduction.reference>
    <reproduction.reference>Z.567 & X-124(2).jpg</reproduction.reference>
    <reproduction.reference>Z.567 & X-124(3).jpg</reproduction.reference>
</record>
</recordList>
</apiXML>

我的担忧:

  1. 有些记录有多个同名的数据成员。像记录 id 31 有 3 个标题
  2. 每条记录的列数不同。

所以我要问的只是我如何处理场景的建议。欢迎任何建议

【问题讨论】:

  • 您有顾虑,但没有提出问题。这使您的担忧更像是观察。观察结果是正确的。但我不认为这是你在这里发帖的目的。
  • @rene 问题很清楚,我要寻找的是,我怎样才能进一步处理这种 xml。寻找遇到类似情况的人。我想这就是我们在这里所做的,分享我们从经验中学到的东西。
  • 所以你的问题是:如果我想存储这个 xml,数据库模式应该是什么样的?
  • 我需要关于这两个方面的建议,我应该如何规划数据库以及代码应该如何解析这样的 XML

标签: c# xml serialization xml-serialization xmlserializer


【解决方案1】:

您需要几个支持类才能按原样反序列化 XML,因为您没有指定任何其他要求。

您的数据库将为您的记录元素和其中的所有集合提供表格。

序列化类

这些类将在内存中保存您的 XML 表示。根将是 Api 类。

[XmlRoot("apiXML")]
public class Api
{
     [XmlArray("recordList")]
     [XmlArrayItem("record", typeof(Record))]
     public List<Record> RecordList {get;set;}
}

[Serializable]
public class Record
{
    [XmlAttribute("id")]
    public int RecordId {get;set;}

    [XmlElement("id")]
    public int Id {get;set;}

    [XmlElement("administration_name")]
    public string AdministrationName {get;set;}

    [XmlElement("object_number")]
    public string ObjectNumber {get;set;}

    [XmlElement("creator")]
    public List<Creator> Creators {get;set;}

    [XmlElement("object_category")]
    public List<ObjectCategory> ObjectCategories {get;set;}

    [XmlElement("reproduction.reference")]
    public List<ReproductionReference> ReproductionReferences {get;set;}

    [XmlElement("title")]
    public List<Title> Titles {get;set;}
}

[Serializable]
public class Title:Child
{
    [XmlAttribute("invariant")]
    public bool Invariant {get;set;}

    [XmlAttribute("lang")]
    public string Culture {get;set;}

    [XmlText]
    public string Text {get;set;}
}

public class Child
{
    [XmlIgnore]
    public int ParentId {get;set;}
}

[Serializable]
public class Creator:Child
{
    [XmlText]
    public string Text {get;set;}
}

[Serializable]
public class ObjectCategory:Child
{
    [XmlText]
    public string Text {get;set;}
}

[Serializable]
public class ReproductionReference:Child
{
    [XmlText]
    public string Text {get;set;}
}

反序列化

使用正确注释的类,反序列化 XML 只需要一对 行数:

var ser = new XmlSerializer(typeof(Api));
var sr = new StringReader(xml);
var api = (Api) ser.Deserialize(sr);

处理和建立表格

在变量api 中,我们现在有内存对象图,您可以将其投影到关系数据库模式上。对于标准化模型,您需要以下表格:

  • 记录(id,[类中的字段])
  • 创建者(id,..)
  • 标题(id, ...)
  • ObjectCategory(id, ...)
  • ObjectNumber (id, ...)
  • ReproductionReference(id, ...)

在这些表之间,您需要遵循所有相同约定的链接表,例如 Record 和 Creator 之间的约定:

  • RecordCreator(RecordId, CreatorId)

我假设您知道如何创建这些表并创建与您的数据库的连接。

// use an SqlAdapter.Fill to get the below  dataset call
// sqlAdapter.Fill(ds);
var ds = new DataSet();
// this is here so you can test without a database
// test mocking code
var recTable = ds.Tables.Add("Record");
recTable.Columns.Add("Id");
recTable.Columns.Add("AdministrationName");
recTable.Columns.Add("ObjectNumber");

var creTable = ds.Tables.Add("Creator");
creTable.Columns.Add("Id", typeof(int)).AutoIncrement = true;
creTable.Columns.Add("Text");

var reccreTable = ds.Tables.Add("RecordCreator");
reccreTable.Columns.Add("RecordId");
reccreTable.Columns.Add("CreatorId");
// end mocking code

// copy object graph and build link tables
foreach(var record in api.RecordList)
{
    // each main record is created
    var rtRow = recTable.NewRow();
    rtRow["Id"] = record.Id;
    rtRow["AdministrationName"] = record.AdministrationName;
    rtRow["ObjectNumber"] = record.ObjectNumber;
    recTable.Rows.Add(rtRow);
    // handle each collection
    foreach(var creator in record.Creators)
    {
        DataRow creRow; // will hold our Creator row
        // first try to find if the Text is already there
        var foundRows = creTable.Select(String.Format("Text='{0}'", creator.Text));
        if (foundRows.Length < 1) 
        {
            // if not, add it to the Creator table
            creRow =  creTable.NewRow(); // Id is autoincrement!
            creRow["Text"] = creator.Text;
            creTable.Rows.Add(creRow);
        }
        else 
        {
            // otherwise, we found an existing one
            creRow = foundRows[0];
        }
        // link record and creator
        var reccreRow = reccreTable.NewRow();
        reccreRow["RecordId"] = record.Id;
        reccreRow["CreatorId"] = creRow["Id"];
        reccreTable.Rows.Add(reccreRow);
   } 

   // the other collections follow a similar pattern but is left for the reader
} 
// now call Update to write the changes to the db.
// SqlDataAdapter.Update(ds); 

您需要在 RDBMS 数据库中存储该 SQL 而不丢失信息所需的代码和结构。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多