C#DataSet XML加载和保存

时间:2013-06-25 14:32:14

标签: c# xml dataset

我有XML描述了我想要编辑的某些数据(模板)。我将XML加载到DataSet中(参见下面的图1),将DataSet表插入DataGridView(使用单独的comboBox在它们之间切换),进行更改然后保存XML(简单的DataSet.WriteXML指令)。我读过的XML看起来非常好看并且具有人性化的可读性(参见下面的图2),然而,书面的XML远不及原版(见下面的图3)。

我的目标是允许编辑XML文档并在保存时以相同的形式保存它。

我做错了什么?代码/ XML块如下所示。

图1 - 将XML读入DataSet:

using (XmlReader xrMeta = XmlReader.Create(new StreamReader(ofdOpenXML.FileName)))
     {
       while (!xrMeta.EOF)
         {
           xrMeta.ReadToFollowing("record");
           if (xrMeta.NodeType == XmlNodeType.Element)
           {
             xrMeta.ReadToFollowing("fields");

             xrSub = xrMeta.ReadSubtree();
             dt = new DataTable();

             ds = new DataSet();

             ds.ReadXml(xrSub);
             dt = ds.Tables[0].Copy();

             dt.TableName = "recordTypeId " + iTableNumber.ToString().PadLeft(2, '0');
             MetaXML.Tables.Add(dt);
             iTableNumber++;
            }

         }

         dgvMetaXML.DataSource = MetaXML.Tables[0];

图2 - 输入XML:

<?xml version='1.0'?>
<records>
  <record>
    <recordTypeId>01</recordTypeId>
    <fields>
      <field>
        <fieldNID>entityID</fieldNID>
        <fieldID>1</fieldID>
        <fieldName>Entity ID</fieldName>
        <fieldStartPos>1</fieldStartPos>
        <fieldEndPos>6</fieldEndPos>
        <fieldLength>6</fieldLength>
        <fieldType>Alpha</fieldType>
        <fieldRequired>Y</fieldRequired>
        <fieldDefaultValue></fieldDefaultValue>
      </field>
      <field>
        <fieldNID>reserved0101</fieldNID>
        <fieldID>2</fieldID>
        <fieldName>Reserved</fieldName>
        <fieldStartPos>7</fieldStartPos>
        <fieldEndPos>8</fieldEndPos>
        <fieldLength>2</fieldLength>
        <fieldType>Alpha</fieldType>
        <fieldRequired>Y</fieldRequired>
        <fieldDefaultValue>  </fieldDefaultValue>
      </field>
      <field>
        <fieldNID>deviceID</fieldNID>
        <fieldID>3</fieldID>
        <fieldName>Device ID</fieldName>
        <fieldStartPos>9</fieldStartPos>
        <fieldEndPos>23</fieldEndPos>
        <fieldLength>15</fieldLength>
        <fieldType>Alpha</fieldType>
        <fieldRequired>Y</fieldRequired>
        <fieldDefaultValue></fieldDefaultValue>
      </field>
    </fields>
  </record>
  <record>
    <recordTypeId>02</recordTypeId>
    <fields>
      <field>
        <fieldNID>userID</fieldNID>
        <fieldID>1</fieldID>
        <fieldName>User ID</fieldName>
        <fieldStartPos>1</fieldStartPos>
        <fieldEndPos>6</fieldEndPos>
        <fieldLength>6</fieldLength>
        <fieldType>Alpha</fieldType>
        <fieldRequired>Y</fieldRequired>
        <fieldDefaultValue></fieldDefaultValue>
      </field>
      <field>
        <fieldNID>reserved0201</fieldNID>
        <fieldID>2</fieldID>
        <fieldName>Reserved</fieldName>
        <fieldStartPos>7</fieldStartPos>
        <fieldEndPos>8</fieldEndPos>
        <fieldLength>2</fieldLength>
        <fieldType>Alpha</fieldType>
        <fieldRequired>Y</fieldRequired>
        <fieldDefaultValue>  </fieldDefaultValue>
      </field>
      <field>
        <fieldNID>testField</fieldNID>
        <fieldID>3</fieldID>
        <fieldName>Test Sequence</fieldName>
        <fieldStartPos>9</fieldStartPos>
        <fieldEndPos>23</fieldEndPos>
        <fieldLength>15</fieldLength>
        <fieldType>Alpha</fieldType>
        <fieldRequired>Y</fieldRequired>
        <fieldDefaultValue></fieldDefaultValue>
      </field>
    </fields>
  </record>
</records>

图3 - 输出XML:

<records>
  <recordTypeId_x0020_01>
    <fieldNID>entityID</fieldNID>
    <fieldID>1</fieldID>
    <fieldName>Entity ID</fieldName>
    <fieldStartPos>1</fieldStartPos>
    <fieldEndPos>6</fieldEndPos>
    <fieldLength>6</fieldLength>
    <fieldType>Alpha</fieldType>
    <fieldRequired>Y</fieldRequired>
    <fieldDefaultValue />
  </recordTypeId_x0020_01>
  <recordTypeId_x0020_01>
    <fieldNID>reserved0101</fieldNID>
    <fieldID>2</fieldID>
    <fieldName>Reserved</fieldName>
    <fieldStartPos>7</fieldStartPos>
    <fieldEndPos>8</fieldEndPos>
    <fieldLength>2</fieldLength>
    <fieldType>Alpha</fieldType>
    <fieldRequired>Y</fieldRequired>
    <fieldDefaultValue />
  </recordTypeId_x0020_01>
  <recordTypeId_x0020_01>
    <fieldNID>deviceID</fieldNID>
    <fieldID>3</fieldID>
    <fieldName>Device ID</fieldName>
    <fieldStartPos>9</fieldStartPos>
    <fieldEndPos>23</fieldEndPos>
    <fieldLength>15</fieldLength>
    <fieldType>Alpha</fieldType>
    <fieldRequired>Y</fieldRequired>
    <fieldDefaultValue />
  </recordTypeId_x0020_01>
  <recordTypeId_x0020_02>
    <fieldNID>userID</fieldNID>
    <fieldID>1</fieldID>
    <fieldName>User ID</fieldName>
    <fieldStartPos>1</fieldStartPos>
    <fieldEndPos>6</fieldEndPos>
    <fieldLength>6</fieldLength>
    <fieldType>Alpha</fieldType>
    <fieldRequired>Y</fieldRequired>
    <fieldDefaultValue />
  </recordTypeId_x0020_02>
  <recordTypeId_x0020_02>
    <fieldNID>reserved0201</fieldNID>
    <fieldID>2</fieldID>
    <fieldName>Reserved</fieldName>
    <fieldStartPos>7</fieldStartPos>
    <fieldEndPos>8</fieldEndPos>
    <fieldLength>2</fieldLength>
    <fieldType>Alpha</fieldType>
    <fieldRequired>Y</fieldRequired>
    <fieldDefaultValue />
  </recordTypeId_x0020_02>
  <recordTypeId_x0020_02>
    <fieldNID>testField</fieldNID>
    <fieldID>3</fieldID>
    <fieldName>Test Sequence</fieldName>
    <fieldStartPos>9</fieldStartPos>
    <fieldEndPos>23</fieldEndPos>
    <fieldLength>15</fieldLength>
    <fieldType>Alpha</fieldType>
    <fieldRequired>Y</fieldRequired>
    <fieldDefaultValue />
  </recordTypeId_x0020_02>
</records>

3 个答案:

答案 0 :(得分:0)

 > The XML I read looks very nice and humanly readable (see fig. 2 below), however, 
 > the written XML is nowhere near the original (see fig. 3 below).
 > What am I doing wrong? 

dotnet数据集只能编写其内部表示的xml格式。 这种表示类似于

  <datasetName>
     <dataTableName OtherFieldName='value'>
         <FieldName>value</FieldName>
     </dataTableName>
  </datasetName>

所以字段是元素或属性。你的xml结构更复杂。 如果可能,数据集会尝试解释您的数据并将数据放入其内部结构中。在您的示例中,信息recordTypeId将丢失。

我遇到了类似的问题并创建了一个我自己的xml-post-processer,它将xml-output重新格式化为我自己的xml格式,数据集可以读取但不能写入。

答案 1 :(得分:0)

您的代码正在使用

每次迭代读取下一个fields条目
xrMeta.ReadToFollowing("fields");

然后,您使用

将基表从fields重命名为recordTypeId XX
dt.TableName = "recordTypeId " + iTableNumber.ToString().PadLeft(2, '0');`

并且空间被编码为_x0020_以避免破坏标记。

然后,将此重命名的fields实例添加回 root

MetaXML.Tables.Add(dt);

输出结果就是这样。

你想要达到什么不同的结果?

答案 2 :(得分:0)

结束k3b的方法(对不起,不能投票 - 需要更多的声誉)。

这是将XML读入DataSet的更新代码(请记住,它只是一个模拟代码,可以让事情第一次起作用。你应该修改它以提高效率并最终更有意义):

int iTableNumber = 1;

// Read input XML
using (XmlReader xrMeta = XmlReader.Create(new StreamReader(ofdOpenXML.FileName)))
{
   while (!xrMeta.EOF)
   {
     // Advance to next <record>
     xrMeta.ReadToFollowing("record");
     if (xrMeta.NodeType == XmlNodeType.Element)
     {
        // Advance to the next <fields>
        xrMeta.ReadToFollowing("fields");

        // Read underlying XML - it will be a set of flat tables
        xrSub = xrMeta.ReadSubtree();
        dt = new DataTable();

        ds = new DataSet("fields");

        ds.ReadXml(xrSub);
        dt = ds.Tables[0].Copy();

        dt.TableName = "field_" + iTableNumber.ToString().PadLeft(2, '0');
        MetaXML.Tables.Add(dt);
        iTableNumber++;
      }
   }
 }

 // Populate comboBox to switch between tables in DataSet
 for (int i = 0; i < MetaXML.Tables.Count; i++)
 {
    cbShowTable.Items.Add(MetaXML.Tables[i].TableName);
 }

 // Populate DataGridView with first read table
 dataGridViewMetaXML.DataSource = MetaXML.Tables[0];

现在保存XML如下所示:

        // This is our output XML file
        // Technically, it should have been the same name as the input one
        // but for the purposes of testing it isn't
        StreamWriter srFile = new StreamWriter((@"testingOutputXML.xml"));
        StringWriter stWriter;
        StringBuilder sbXML = new StringBuilder();

        // Headers to play nice
        sbXML.AppendLine("<?xml version='1.0'?>");
        sbXML.AppendLine("<records>");
        DataTable dt;
        for (int i = 0; i < MetaXML.Tables.Count; i++)
        {
            // This is where we have to recreate the structure manually
            sbXML.AppendLine("<record>");
            sbXML.Append("<recordTypeId>");
            sbXML.Append((1+ i).ToString().PadLeft(2,'0'));
            sbXML.AppendLine("</recordTypeId>");
            dt = new DataTable();
            dt = MetaXML.Tables[i].Copy();
            dt.TableName = "field";

            stWriter = new StringWriter();
            dt.WriteXml(stWriter, false);              
            stWriter.WriteLine();

            sbXML.Append(stWriter.GetStringBuilder());

            // Need to clean up because DataTable's WriteXML() method
            // wraps the data in <DocumentElement> and </DocumentElement> tags
            sbXML.Replace("DocumentElement", "fields");
            sbXML.AppendLine("</record>");
        }
        sbXML.AppendLine("</records>");
        srFile.Write(sbXML.ToString());
        srFile.Flush();
        srFile.Close();

        MessageBox.Show("Done!");

感谢所有插入答案的人,它引导我走上了正确的轨道。