2013-06-25 5 views
0

У меня есть XML, который описывает определенные данные (шаблон), которые я хочу редактировать. Я загружаю XML в DataSet (см. Рис.1 ниже), вставляйте таблицы DataSet в DataGridView (переключайтесь между ними с помощью отдельного comboBox), вносите изменения и затем сохраняете XML (простая директива DataSet.WriteXML). XML, который я читаю, выглядит очень красиво и по-человечески читаемым (см. Рис.2 ниже), однако письменный XML нигде не находится рядом с оригиналом (см. Рис. 3 ниже).C# DataSet Загрузка и сохранение XML-данных

Моя цель - разрешить редактирование XML-документа и сохранить его в той же форме при сохранении.

Что я делаю неправильно? Ниже приведены блоки кода/XML.

fig.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> 

ответ

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!"); 

Спасибо всем, кто скинулся с ответами, он поворачиваемым меня к правильном пути.

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> 

Итак поля элементы или attributs. Ваша xml-структура более сложна. Набор данных пытается интерпретировать ваши данные и по возможности помещает данные во внутреннюю структуру. В вашем примере потеряна информация recordTypeId.

У меня была аналогичная проблема и я создал свой собственный xml-пост-процесс, который переформатировал xml-вывод в мой собственный XML-формат, который набор данных может читать, но не писать.

+0

Я надеялся, что это моя ошибка, а не недостаток рамки :) Каков наилучший подход для такого случая? Просто вручную создайте XML? Или что-то другое? – Vlad

0

Ваш код чтения к следующему fields записи с каждой итерации с помощью

xrMeta.ReadToFollowing("fields"); 

Вы тогда переименовывать базовую таблицу из fields в recordTypeId XX с

dt.TableName = "recordTypeId " + iTableNumber.ToString().PadLeft(2, '0');` 

и пространство кодируемого до _x0020_, чтобы избежать разрыва тега.

Вы затем добавить этот переименованный экземпляр fields обратно в корень с

MetaXML.Tables.Add(dt); 

Выход является результатом этого.

Какой другой результат вы пытались достичь?

+0

Я пытаюсь получить XML так же, как и для чтения. Спасибо, что указали это, я уточню свой вопрос. – Vlad

+0

Почему бы вам не привязать и сохранить исходный набор данных или его клон? Это позволит вам выводить без каких-либо изменений в схему. –

+0

Роб, можете ли вы привести пример того, что вы подразумеваете под привязкой и сохранить в наборе данных? Не уверен, что связано и спасено. – Vlad