2013-03-07 2 views
0

Я хочу, чтобы преобразовать XML строку Datatable.String, как этоXML в DataTable преобразования терпит неудачу

<TextstringArray> 
    <values> 
     <value>athul</value> 
     <value>[email protected]</value> 
     <value>1</value> 
    </values> 
    <values> 
     <value>arun</value> 
     <value>[email protected]</value> 
     <value>1</value> 
    </values> 
    <values> 
     <value>ajmal</value> 
     <value>[email protected]</value> 
     <value>1</value> 
    </values> 
</TextstringArray> 

Я пытался что-то вроде этого

StringReader theReader = new StringReader(invitations); 
DataSet theDataSet = new DataSet(); 
theDataSet.ReadXml(theReader); 

Но datatset выходит с неправильно отформатированные данные. как все элементы стоимости приходит в одинарных column.I хочет их в три columns.one для первых и так далее. (Xml получает в таблицу, но не структуру XML)

enter image description here

+0

Каким образом данные неправильно отформатирован? (Что вы получаете? Что вы ожидали?) – Richard

+0

Что не так в вашем формате? – Alex

+0

Вы заметили, что в DataSet есть фактически 2 DataTable? –

ответ

0

Вы могли бы использовать некоторую доброжелательность LINQy для группировки и проекта в новую структуру данных.

Обратите внимание, что следующий код ожидает, что в каждой группе должно быть ровно 3 значения, и полагается на согласованный вход. Если это не так, вам нужно будет адаптировать его к своей среде.

StringReader theReader = new StringReader(invitations); 
DataSet theDataSet = new DataSet(); 
theDataSet.ReadXml(theReader); 

// Get the table we are interested in. 
var dt = theDataSet.Tables["value"]; 

// Group by the "values_Id" field. This is what logically 
// relates each <value>. 
// Then, project out a new type, assuming that the first row 
// holds the username, the second holds the email address, 
// and the third holds "some thing else". 
var rows = dt.Rows. 
    Cast<DataRow>(). 
    GroupBy(dr => dr["values_Id"]). 
    Select(row => 
     new 
     { 
      RowId = row.Key, 
      UserName = row.ElementAt(0)["value_Text"], 
      UserEmail = row.ElementAt(1)["value_Text"], 
      UserOtherValue = row.ElementAt(2)["value_Text"] 
     }); 

foreach (var row in rows) 
{ 
    Console.WriteLine("Row " + row.RowId); 
    Console.WriteLine(" UserName: " + row.UserName); 
    Console.WriteLine(" Email: " + row.UserEmail); 
    Console.WriteLine(" OtherValue: " + row.UserOtherValue); 
} 

Производит следующий вывод:

Row 0 
    UserName: athul 
    Email: [email protected] 
    OtherValue: 1 
Row 1 
    UserName: arun 
    Email: [email protected] 
    OtherValue: 1 
Row 2 
    UserName: ajmal 
    Email: [email protected] 
    OtherValue: 1 
1

Для того, чтобы достичь своей цели, XML должен иметь следующую структуру:

<TextstringArray> 
    <values> 
     <value1>athul</value1> 
     <value2>[email protected]</value2> 
     <value3>1</value3> 
    </values> 
    <values> 
     <value1>arun</value1> 
     <value2>[email protected]</value2> 
     <value3>1</value3> 
    </values> 
    <values> 
     <value1>ajmal</value1> 
     <value2>[email protected]</value2> 
     <value3>1</value3> 
    </values> 
</TextstringArray> 

Это произведет один сингл DataTable, где каждый Элемент values будет источником строки данных, в то время как каждый дочерний элемент (value1, value2 и т. Д.) Будет считан как колония п.

Обходной бы:

StringReader theReader = new StringReader(File.ReadAllText(invitations)); 
DataSet theDataSet = new DataSet(); 
theDataSet.ReadXml(theReader); 

var valueIdsDatatable = theDataSet.Tables[0]; 
var valueDatatable = theDataSet.Tables[1]; 

// detect the maximum number of columns 
var maxColumns = valueDatatable.AsEnumerable() 
    .GroupBy(i => i["values_Id"]).Max(i => i.Count()); 

// create the result DataTable 
var resultDataTable = new DataTable(); 

// add dynamically the columns 
for (int i = 0; i < maxColumns; i++) 
{ 
    resultDataTable.Columns.Add("property" + i); 
} 

// add the rows 
foreach (DataRow valueId in valueIdsDatatable.Rows) 
{ 
    var newRow = resultDataTable.NewRow(); 
    var currentRows = valueDatatable.Select("values_id = " + valueId[0]); 
    for (int i = 0; i < currentRows.Length; i++) 
    { 
     newRow[i] = currentRows[i][0]; 
    } 
    resultDataTable.Rows.Add(newRow); 
} 

// TODO: use the resultDataTable 
+0

его невозможно для меня изменить способ xml приходит, его от внешнего api.Is там любой другой способ? – Binoop

+0

@Arun Я отправил один вариант в свой ответ. Обратите внимание, что это будет хрупким и не будет хорошо работать с изменениями в формате XML. Однако любое предлагаемое решение будет иметь эту проблему. –

+0

@RB, _... любое предлагаемое решение будет иметь эту проблему. На самом деле, если вы не делаете никаких предположений о количестве или порядке детей 'value'. Во время сериализации порядок обработки не гарантируется, если атрибуты не используются в представлении класса для его управления. –

Смежные вопросы