I'm accessing a SharePoint(2007) list through a service reference of lists.asmx created in my console application. Console application is created in VS2012 and .Net 4.5 framework.
ListsSoapClient proxy1 = new ListsSoapClient();
proxy1.ClientCredentials.Windows.ClientCredential = System.Net.CredentialCache.DefaultNetworkCredentials;
proxy1.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
string listName = "List_For_Test";
DataSet ds1 = new DataSet();
XElement ndQuery = new XElement("Query", "");
XElement ndViewFields = new XElement("ViewFields", "");
XElement ndQueryOptions = new XElement("QueryOptions", "");
XElement items = proxy1.GetListItems(listName, null, ndQuery, ndViewFields, null, ndQueryOptions, null);
ds1 = XElementToDataSet(items);
I need to convert the XML returned in items XElement to dataset/datatable and pass it to a stored procedure written in SQL Server 2008 R2.
I tried using following code but it gave me error
XElement setup = (from p in x.Descendants() select p).First();
foreach (XElement xe in setup.Descendants()) // build your DataTable
dt.Columns.Add(new DataColumn(xe.Name.ToString(), typeof(string)));
// on second iteration gave error that "'{#RowsetSchema}row'" column already existing.
This is the XML stream returned from GetListItems() webservice method call
<listitems xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882"
xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882"
xmlns:rs="urn:schemas-microsoft-com:rowset" xmlns:z="#RowsetSchema"
xmlns="http://schemas.microsoft.com/sharepoint/soap/"> <rs:data
ItemCount="2"> <z:row
ows_ContentTypeId="0x01006B57C3DFF39626458A729755ABF3A370"
ows_Title="Item#1" ows_ListID="1.00000000000000"
ows_Loan_x0020_Number="1234.00000000000" ows_ID="2"
ows_ContentType="Item" ows_Modified="2014-04-01 10:06:38"
ows_Created="2014-04-01 10:06:38" ows_Author="7017;#, Khushi"
ows_Editor="7017;#, Khushi" ows_owshiddenversion="1"
ows_WorkflowVersion="1" ows__UIVersion="512"
ows__UIVersionString="1.0" ows_Attachments="0"
ows__ModerationStatus="0" ows_LinkTitleNoMenu="Item#1"
ows_LinkTitle="Item#1" ows_SelectTitle="2"
ows_Order="200.000000000000"
ows_GUID="{2832ED2B-A45D-4950-8E0E-EEB3E31199AF}" ows_FileRef="2;#
List_For_Test/2_.000" ows_FileDirRef="2;#/List_For_Test"
ows_Last_x0020_Modified="2;#2014-04-01 10:06:38"
ows_Created_x0020_Date="2;#2014-04-01 10:06:38" ows_FSObjType="2;#0"
ows_PermMask="0x7fffffffffffffff" ows_FileLeafRef="2;#2_.000"
ows_UniqueId="2;#{F3336392-74F7-45C2-A175-EF36DA219812}"
ows_ProgId="2;#"
ows_ScopeId="2;#{E9E1B331-7993-4586-93DC-3690EBEBAD9E}"
ows__EditMenuTableStart="2_.000" ows__EditMenuTableEnd="2"
ows_LinkFilenameNoMenu="2_.000" ows_LinkFilename="2_.000"
ows_ServerUrl="/ List_For_Test/2_.000"
ows_EncodedAbsUrl="Lists/List_For_Test/2_.000" ows_BaseName="2_"
ows_MetaInfo="2;#" ows__Level="1" ows__IsCurrentVersion="1" />
<z:row ows_ContentTypeId="0x01006B57C3DFF39626458A729755ABF3A370"
ows_Title="Item#2" ows_ListID="2.00000000000000"
ows_Loan_x0020_Number="5678.00000000000" ows_ID="3"
ows_ContentType="Item" ows_Modified="2014-04-01 10:06:53"
ows_Created="2014-04-01 10:06:53" ows_Author="7017;#Khushi"
ows_Editor="7017;#, Khushi" ows_owshiddenversion="1"
ows_WorkflowVersion="1" ows__UIVersion="512"
ows__UIVersionString="1.0" ows_Attachments="0"
ows__ModerationStatus="0" ows_LinkTitleNoMenu="Item#2"
ows_LinkTitle="Item#2" ows_SelectTitle="3"
ows_Order="300.000000000000"
ows_GUID="{8A6C6A66-A795-4054-B793-789B739EA881}" ows_FileRef="3;#
/List_For_Test/3_.000" ows_FileDirRef="3;# /List_For_Test"
ows_Last_x0020_Modified="3;#2014-04-01 10:06:53"
ows_Created_x0020_Date="3;#2014-04-01 10:06:53" ows_FSObjType="3;#0"
ows_PermMask="0x7fffffffffffffff" ows_FileLeafRef="3;#3_.000"
ows_UniqueId="3;#{434E5737-5591-4A02-91E5-B2C7A2EFF2B3}"
ows_ProgId="3;#"
ows_ScopeId="3;#{E9E1B331-7993-4586-93DC-3690EBEBAD9E}"
ows__EditMenuTableStart="3_.000" ows__EditMenuTableEnd="3"
ows_LinkFilenameNoMenu="3_.000" ows_LinkFilename="3_.000"
ows_ServerUrl="/List_For_Test/3_.000"
ows_EncodedAbsUrl="Lists/List_For_Test/3_.000" ows_BaseName="3_"
ows_MetaInfo="3;#" ows__Level="1" ows__IsCurrentVersion="1" />
</rs:data> </listitems>
Please check it here...
public static class XElementExtensions {
public static DataTable ToDataTable(this XElement element) {
DataSet ds = new DataSet();
string rawXml = element.ToString();
ds.ReadXml(new StringReader(rawXml));
return ds.Tables[0];
}
public static DataTable ToDataTable(this IEnumerable<XElement> elements) {
return ToDataTable(new XElement("Root", elements));
}
}
Use it like this:
protected void Page_Load(object sender, EventArgs e) {
string xmlFile = Server.MapPath("~/Data.xml");
XDocument document = XDocument.Load(xmlFile);
var booksQuery = from b in document.Elements("NewDataSet").Elements("Table")
select b;
DataTable table = booksQuery.ToDataTable();
GridView1.DataSource = table;
GridView1.DataBind();
}
khushi,check this may be useful to you....
public static DataSet XElementToDataSet(XElement xeRecordsList)
{
DataTable dtRecordsList = new DataTable();
XElement setup = (from p in xeRecordsList.Descendants() select p).First();
// builds DataTable
foreach (XElement xe in setup.Descendants())
dtRecordsList.Columns.Add(new DataColumn(xe.Name.ToString(), typeof(string)));
// add columns to your dt
var all = from p in xeRecordsList.Descendants(setup.Name.ToString()) select p;
foreach (XElement xe in all)
{
DataRow dr = dtRecordsList.NewRow();
//adding the values
foreach (XElement xe2 in xe.Descendants())
{
bool boolColExists = false;
//Check for column exists in datatable
foreach (DataColumn col in dtRecordsList.Columns)
{
if (col.ColumnName == xe2.Name.ToString())
{
boolColExists = true;
break;
}
}
if (boolColExists)
dr[xe2.Name.ToString()] = xe2.Value;
}
dtRecordsList.Rows.Add(dr);
}
DataSet dstRecordsList = new DataSet("RECORDLIST");
dstRecordsList.Tables.Add(dtRecordsList);
dstRecordsList.Tables[0].TableName = "RECORD";
return dstRecordsList;
}
some references:
http://www.dotnetpickles.com/2014/02/aspnet-convert-xml-to-datatable-in-cnet.html
Related
There is no problem in converting static columns to xml
The problem is that I'm trying to make the conversion through an array and insert it as I need it every time
can you add
loop to XElement
string creatColumnXml(params int[] ColId)
{
return new XElement(table.TableName, table.Rows.Cast<DataRow>().Select(row =>
new XElement("row",
//for ( int i =0;i<ColId.Length;i++)
//new XElement(table.Columns[ColId[i]].ColumnName, row[ColId[i]]),
new XElement(table.Columns[0].ColumnName, row[0]),
new XElement(table.Columns[1].ColumnName, row[1]),
new XElement(table.Columns[2].ColumnName, row[2])
))
).ToString();
}
You can use LINQ again within your existing lambda
string creatColumnXml(params int[] ColId)
{
return new XElement(table.TableName,
table.Rows.Cast<DataRow>().Select(row =>
new XElement("row",
ColId.Select(c => new XElement(table.Columns[c].ColumnName, row[c]))
)
).ToString();
}
I found the solution
XElement[] c = new XElement[ColId.Length];
XElement[] r = new XElement[table.Rows.Count];
int y = 0;
string s="" ;
foreach (DataRow row in table.Rows)
{
for (int i = 0; i < ColId.Length; i++)
{
c[i] = new XElement(table.Columns[ColId[i]].ColumnName, row[ColId[i]]);
}
r[y] = new XElement("row",c);
y++;
}
s = new XElement(table.TableName, r).ToString();
Assuming you got your DataRows from a DataSet, you can just directly convert the DataSet to XML using the DataSet.WriteXml method.
Here's an example, hope this is helpful.
DataSet MainDS = new DataSet();
SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = new SqlCommand( "select name, city, country from user" );
da.Fill(MainDS, "row");
XmlDocument xml = new XmlDocument();
using (MemoryStream ms = new MemoryStream()) {
try {
XmlWriterSettings settings = new XmlWriterSettings();
settings.Encoding = Encoding.UTF8;
settings.CheckCharacters = false;
using (XmlWriter xmlWriter = XmlWriter.Create(ms, settings)) {
MainDS.WriteXml(xmlWriter);
xmlWriter.Close();
}
ms.Position = 0;
xml.Load(ms);
} catch (Exception err) {
throw new Exception("Error loading dataset to xml", err);
}
}
From there, use XSL to format.
You can also direct .NET to create attribute based XML.
foreach (System.Data.DataTable dt in ds.Tables) {
foreach (DataColumn dc in dt.Columns) {
dc.ColumnMapping = MappingType.Attribute;
}
}
I have this dataset like this:
How can I get the string "TITLE" and "SUMMARY"?
I have this code:
string path = #"C:\Users\Pichau\Downloads\teste\data.xml";
XmlDocument x = new XmlDocument();
x.Load(path);
StringReader stream = new StringReader(x.InnerXml);
DataSet ds = new DataSet();
ds.ReadXml(stream);
foreach (var i in ds.Tables["col"].Columns)
{
Console.WriteLine(i.ToString());
}
Console.ReadLine();
But with this code I get the following output:
name
type
col_Text
row_Id
I want to access the value of "TITLE" in the "name" column
You will need to find the DataRow that corresponds to your TITLE and SUMMARY rows, and then access the values of the appropriate columns.
Try this:
foreach (DataRow row in ds.Tables["col"].Rows) {
if (row["name"] == "TITLE") {
Console.WriteLine(row["col_Text"]);
}
}
Hi i am reading the RSS feed and creating an XML using the DataTable. This is my code
try
{
DataTable tbl = new DataTable();
tbl.Columns.Add("id");
tbl.Columns.Add("product_name");
tbl.Columns.Add("description");
//Extra Nodes
tbl.Columns.Add("brand");
tbl.Columns.Add("condition");
tbl.Columns.Add("product_type");
XmlDocument doc = new XmlDocument();
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(s);
XmlNodeList itemNodes = xmlDoc.SelectNodes("//rss/channel/item");
foreach (XmlNode itemNode in itemNodes)
{
DataRow row = tbl.NewRow();
XmlNode idNode = itemNode.SelectSingleNode("id");
XmlNode product_nameNode = itemNode.SelectSingleNode("product_name");
XmlNode descriptionNode = itemNode.SelectSingleNode("description");
//extra nodes
XmlNode brandNode = itemNode.SelectSingleNode("brand");
XmlNode conditionNode = itemNode.SelectSingleNode("condition");
XmlNode product_typeNode = itemNode.SelectSingleNode("product_type");
if (idNode != null && product_nameNode != null && descriptionNode != null )
{
row[0] = idNode.InnerText;
row[1] = product_nameNode.InnerText;
row[2] = descriptionNode.InnerText;
//extra nodes
if (brandNode == null)
row[3] = "";
else
row[3] = brandNode.InnerText;
if (conditionNode==null)
row[4] = "";
else
row[4] = conditionNode.InnerText;
if (product_typeNode==null)
row[5] = "";
else
row[5] = product_typeNode.InnerText;
}
tbl.Rows.Add(row);
// tbl.Rows.Add(row);
}
}
}
catch (Exception ex)
{
// Console.WriteLine(ex.Message);
// Console.Read();
}
This is working fine without any issue but i want to make my code more efficient. Is this the good way to read the Rss and add into the datatable ? I am making a SSIS project on VS 2008 so i can not use SyndicationFeed .
You can use this code below ans use as example.
using System;
using System.ServiceModel.Syndication;
using System.Xml;
namespace RSSFeed
{
public class Program
{
static void Main(string[] args)
{
// URL from the site you need (RSS Feed in XML please).
String url = "http://www.medicalnewstoday.com/rss/abortion.xml";
// Create XML Reader.
using (XmlReader xmlReader = XmlReader.Create(url, new XmlReaderSettings() { DtdProcessing = DtdProcessing.Ignore }))
{
// Load The Feed.
SyndicationFeed syndicationFeed = SyndicationFeed.Load(xmlReader);
// through the list.
foreach (SyndicationItem item in syndicationFeed.Items)
{
// You can use a lot of information here todo what you need.
// TODO...
// Examples
String subject = item.Title.Text;
String summary = item.Summary.Text;
}
xmlReader.Close();
}
}
}
}
I’m a LINQ beginner and need some help. Below is the important part of the generated XML generated by a rest query.
<FormData FormOID="F_TABLEOFMODAL_V20" OpenClinica:Version="v2.0" OpenClinica:Status="initial data entry">
<ItemGroupData ItemGroupOID="IG_TABLE_MODALITYTABLE" ItemGroupRepeatKey="3" TransactionType="Insert">
<ItemData ItemOID="I_TABLE_MODAL_DATE_TABLE" Value="2014-04-10" />
<ItemData ItemOID="I_TABLE_MODAL_TYPE_TABLE" Value="4" />
</ItemGroupData>
<ItemGroupData ItemGroupOID="IG_TABLE_MODALITYTABLE" ItemGroupRepeatKey="1" TransactionType="Insert">
<ItemData ItemOID="I_TABLE_MODAL_DATE_TABLE" Value="2014-04-01" />
<ItemData ItemOID="I_TABLE_MODAL_TYPE_TABLE" Value="2" />
</ItemGroupData>
<ItemGroupData ItemGroupOID="IG_TABLE_MODALITYTABLE" ItemGroupRepeatKey="2" TransactionType="Insert">
<ItemData ItemOID="I_TABLE_MODAL_DATE_TABLE" Value="2014-04-04" />
<ItemData ItemOID="I_TABLE_MODAL_TYPE_TABLE" Value="1" />
</ItemGroupData>
</FormData>
What i want to get to are the ItemOIDs. My question is is there some way to get Values for all ItemOID="I_TABLE_MODAL_DATE_TABLE"(ans: two dates) and ItemOID="I_TABLE_MODAL_TYPE_TABLE" (ans: two numbers). The code below works but this uses ItemData for the first element (called date) and then skipping one to second element (type).
////Print out xml to use?
var doc = XDocument.Load(XmlReader.Create(streaming));
XNamespace nsSys = "http://www.cdisc.org/ns/odm/v1.3";
//loop through <ItemGroupData> to get both date and type value
//from each iteration
var items = from i in doc.Descendants(nsSys + "ItemGroupData")
select new
{
date = (string)i.Element(nsSys + "ItemData").Attribute("Value"),
type = (string)i.Descendants(nsSys + "ItemData").Skip(1).First().Attribute("Value")
};
//Catch here?
DataTable modDt = new DataTable();
modDt.Columns.Add(new DataColumn("Date", typeof(string)));
modDt.Columns.Add(new DataColumn("Type", typeof(string))); //changed to string?
//add LINQ-to-XML query result to DataTable
foreach (var item in items)
{
//convert item.date string to DateTime
//then convert it back to string with different format
modDt.Rows.Add(DateTime.ParseExact(item.date, "yyyy-MM-dd", CultureInfo.InvariantCulture)
.ToString("MM/dd/yy"),
int.Parse(item.type));
}
//Value of OC output
//1=mr,2=ct,3=pet,4=us,5=meg,6=ecg (put if statements before xnat rest ssh string)
for (int i = 0; i <= modDt.Rows.Count - 1; i++)
{
modDt.Rows[i][1] = modDt.Rows[i][1].ToString().Replace("1", "mr");
modDt.Rows[i][1] = modDt.Rows[i][1].ToString().Replace("2", "ct");
modDt.Rows[i][1] = modDt.Rows[i][1].ToString().Replace("3", "pet");
modDt.Rows[i][1] = modDt.Rows[i][1].ToString().Replace("4", "us");
modDt.Rows[i][1] = modDt.Rows[i][1].ToString().Replace("5", "meg");
modDt.Rows[i][1] = modDt.Rows[i][1].ToString().Replace("6", "ecg");
}
I've started writting some code shown below. The adding of data into datatable still does not work sorry. However the idea of what i'm trying to do is in there.
DataTable modDt = new DataTable();
modDt.Columns.Add(new DataColumn("Date", typeof(string)));
modDt.Columns.Add(new DataColumn("Type", typeof(string))); //changed to string?
var document = XDocument.Load("doc.xml");
XNamespace nsSys = "http://www.cdisc.org/ns/odm/v1.3";
//Get nodes separated by inner child element
var itd = document.Descendants(nsSys + "ItemData")
.Where(t => (string)t.Attribute("ItemOID") == "I_TABLE_MODAL_DATE_TABLE");
var itds = itd.Attributes("Value").ToArray();
foreach (var it in itds)
{
var subA = it.ToString();
var subAA = subA.ToCharArray();
var subB = subAA.Skip(9).Take(8).ToArray();
string sub = new string(subB);
var subBB = sub.Split('-').ToArray();
string subC = subBB[1] + "/" + subBB[2] + "/" + subBB[0];
foreach (DataRow dr in modDt.Rows)
{
dr["Date"] = subC;
}
Console.WriteLine(subC);
}
var itt = document.Descendants(nsSys + "ItemData")
.Where(t => (string)t.Attribute("ItemOID") == "I_TABLE_MODAL_TYPE_TABLE");
var itty = itt.Attributes("Value").ToArray();
foreach (var et in itty)
{
var subz = et.ToString();
var subzz = subz.ToCharArray();
var subx = subzz.Skip(7).Take(1).ToArray();
string subxx = new string(subx);
foreach (DataRow dt in modDt.Rows)
{
dt["Type"] = subxx;
}
Console.WriteLine(subxx);
}
//for (int i = 0; i <= modDt.Rows.Count - 1; i++)
//{
// modDt.Rows[i][1] = modDt.Rows[i][1].ToString().Replace("1", "mr");
// modDt.Rows[i][1] = modDt.Rows[i][1].ToString().Replace("2", "ct");
// modDt.Rows[i][1] = modDt.Rows[i][1].ToString().Replace("3", "pet");
// modDt.Rows[i][1] = modDt.Rows[i][1].ToString().Replace("4", "us");
// modDt.Rows[i][1] = modDt.Rows[i][1].ToString().Replace("5", "meg");
// modDt.Rows[i][1] = modDt.Rows[i][1].ToString().Replace("6", "ecg");
//}
foreach (DataRow row in modDt.Rows) // Loop over the rows.
{
string sessionDate = row["Date"].ToString();
string mod = row["Type"].ToString();
string drow = "aa" + sessionDate + "bb" + mod + "cc";
Console.WriteLine(drow);
}
Console.Read();
Thank you so much for your help and your time. It is greatly appreciated. Cheers.
Current Attempt
DataTable modDt = new DataTable();
modDt.Columns.Add(new DataColumn("Date", typeof(string)));
modDt.Columns.Add(new DataColumn("Type", typeof(string))); //changed to string?
var document = XDocument.Load("doc.xml");
XNamespace nsSys = "http://www.cdisc.org/ns/odm/v1.3";
//Get nodes separated by inner child element
var values = document.Descendants(nsSys + "ItemData")
.Where(t => t.Attribute("ItemOID").Value == "I_TABLE_MODAL_DATE_TABLE")
.Select(x => x.Attribute("Value").Value);
foreach (var item in values)
{
modDt.Rows.Add(DateTime.ParseExact(item, "yyyy-MM-dd", CultureInfo.InvariantCulture).ToString("MM/dd/yy"),null);
}
var typevalues = document.Descendants(nsSys + "ItemData")
.Where(t => t.Attribute("ItemOID").Value == "I_TABLE_MODAL_TYPE_TABLE")
.Select(x => x.Attribute("Value").Value);
foreach (var item in typevalues)
{
modDt.Rows.Add(null ,int.Parse(item));
}
foreach (DataRow row in modDt.Rows)
{
string sessionDate = row["Date"].ToString();
string mod = row["Type"].ToString();
string xnatCli = mod + sessionDate;
Console.Write(xnatCli);
}
i am trying to answer your question in a single line of code
var values = document.Descendants("ItemData")
.Where(t => t.Attribute("ItemOID").Value == "I_TABLE_MODAL_DATE_TABLE")
.Select(x => x.Attribute("Value").Value)
after this line the values collection will have all the dates. same can be applied to other queries as well.
Update: the solution below use linq to sql, assuming class FormDataContext is prepared for connecting database to relevant table.
FormDataContext db = new FormDataContext();
[Table(Name = "FormData")]
public class FormData
{
[Column]
public DateTime Date;
[Column]
public int Type;
}
IEnumerable<FormData> values = document.Descendants("ItemGroupData").Select(t => {
return new FormData {
FormDate = Convert.ToDateTime(t.XPathSelectElement("ItemData[#ItemOID='I_TABLE_MODAL_DATE_TABLE']").Attribute("Value").Value),
Type = Convert.ToInt32(t.XPathSelectElement("ItemData[#ItemOID='I_TABLE_MODAL_TYPE_TABLE']").Attribute("Value").Value)
};
});
foreach (FormData data in values) {
db.Form.InsertOnSubmit(data);
}
db.SubmitChanges();
This is just an example to store the required two fields to db. You may adjust the example based on your needs.
string parseData= "<TEST xmlns:dt=\"urn:schemas-microsoft-com:datatypes\"><A dt:dt=\"string\">10</A><B dt:dt=\"string\">20</B></TEST>";
DataSet ds = new DataSet("Whatev");
TextReader txtReader = new StringReader(parseData);
XmlReader reader = new XmlTextReader(txtReader);
ds.ReadXml(reader);
DataTable ad = new DataTable("newT");
ad.ReadXml(reader);
For this I am getting empty table in ad, and three tables in ds.
What I am expecting is,
one table with two columns A and B, and one row with values 10 and 20.
What am I doing wrong?
You're simply not using it correctly. There's a number of problems:
You are reading from the same stream twice. In the first pass, the stream pointer is at the end of the stream. You attempt to read from it again when it's already at the end so nothing else is read. Either read into your data set or into your data table, not both. Or, at least seek back to the beginning of the stream if you really want to.
Your XML is not in the correct format. It has to be in the format:
<SomeRoot>
<TableName>
<ColumnName>ColumnValue</ColumnName>
</TableName>
<TableName>
<ColumnName>AnotherColumnValue</ColumnName>
</TableName>
</SomeRoot>
You won't be able to use that method with any arbitrary XML.
Your tables do not have a schema set. You need to either read in a schema or set it up beforehand.
var table = new DataTable("TEST");
table.Columns.Add("A", typeof(string));
table.Columns.Add("B", typeof(string));
table.ReadXml(xmlReader);
Try this instead:
var xmlStr = #"<Root>
<TEST>
<A>10</A>
<B>20</B>
</TEST>
</Root>";
var table = new DataTable("TEST");
table.Columns.Add("A", typeof(string));
table.Columns.Add("B", typeof(string));
table.ReadXml(new StringReader(xmlStr));
If you decide to parse that XML yourself, LINQ can help you out here.
public static DataTable AsDataTable(XElement root, string tableName, IDictionary<string, Type> typeMapping)
{
var table = new DataTable(tableName);
// set up the schema based on the first row
XNamespace dt = "urn:schemas-microsoft-com:datatypes";
var columns =
(from e in root.Element(tableName).Elements()
let typeName = (string)e.Element(dt + "dt")
let type = typeMapping.ContainsKey(typeName ?? "") ? typeMapping[typeName] : typeof(string)
select new DataColumn(e.Name.LocalName, type)).ToArray();
table.Columns.AddRange(columns);
// add the rows
foreach (var rowElement in root.Elements(tableName))
{
var row = table.NewRow();
foreach (var column in columns)
{
var colElement = rowElement.Element(column.ColumnName);
if (colElement != null)
row[column.ColumnName] = Convert.ChangeType((string)colElement, column.DataType);
}
table.Rows.Add(row);
}
return table;
}
Then to use it:
var xmlStr = #"<Root>
<TEST xmlns:dt=""urn:schemas-microsoft-com:datatypes"">
<A dt:dt=""string"">10</A>
<B dt:dt=""string"">20</B>
</TEST>
</Root>";
var root = XElement.Parse(xmlStr);
var mapping = new Dictionary<string, Type>
{
{ "string", typeof(string) },
};
var table = AsDataTable(root, "TEST", mapping);
There probably is a better way to get the associated .NET type for a datatype but I don't know how to do that at the moment, I'll update if I find that out.