I have some XML in a string in memory exactly like this:
<symbols>
<symbol>EURCHF</symbol>
<symbol>EURGBP</symbol>
<symbol>EURJPY</symbol>
<symbol>EURUSD</symbol>
</symbols>
I want to read this into a DataTable. I am doing it like this:
DataTable dt = new DataTable();
dt.TableName = "symbols";
dt.Columns.Add("symbol");
if (!String.IsNullOrEmpty(symbols))
{
dt.ReadXml(new StringReader(symbols));
}
However when I check the number of rows, the DataTable ends up having zero rows. What am I doing wrong?
From here: http://www.dreamincode.net/code/snippet3186.htm
// <summary>
/// method for reading an XML file into a DataTable
/// </summary>
/// <param name="file">name (and path) of the XML file</param>
/// <returns></returns>
public DataTable ReadXML(string file)
{
//create the DataTable that will hold the data
DataTable table = new DataTable("XmlData");
try
{
//open the file using a Stream
using(Stream stream = new FileStream(file, FileMode.Open, FileAccess.Read))
{
//create the table with the appropriate column names
table.Columns.Add("Name", typeof(string));
table.Columns.Add("Power", typeof(int));
table.Columns.Add("Location", typeof(string));
//use ReadXml to read the XML stream
table.ReadXml(stream);
//return the results
return table;
}
}
catch (Exception ex)
{
return table;
}
}
You might want to take a look at DataTable.ReadXml method.
EDIT: If you have xml object in memory you can use the ReadXml method directly. DataTable.ReadXml(MemoryStream Object);
EDIT 2: I did the export. The following XML Schema is required:
<?xml version="1.0" standalone="yes"?>
<DocumentElement>
<symbols>
<symbol>EURCHF</symbol>
</symbols>
<symbols>
<symbol>EURGBP</symbol>
</symbols>
<symbols>
<symbol>EURJPY</symbol>
</symbols>
</DocumentElement>
I've been searching for a easy way to do the same for some time too, but never really found what I actually wanted. Here's one solution I came across. It works, but I don't really like it as I first have to write the file into a DataSet and then put the created DataSet-Table into a DataTable.
Anyway, here's the code:
DataSet ds = new DataSet();
ds.ReadXml(path);
DataTable newDataTable = ds.Tables[0];
I also tried .ReadXml on my DataTable but that always threw an Exception.
I'm not happy with this solution, but it at least works.
Like this:
Dim strXmlString As String = "<tables><row><table_name>Table1</table_name><record_key>1</record_key></row>"
strXmlString += "<row><table_name>Table2</table_name><record_key>2</record_key></row></tables>"
Dim srXMLtext As System.IO.StringReader = New System.IO.StringReader(strXmlString)
Dim dt As New DataTable
dt.ReadXml(srXMLtext)
Another way:
public DataTable ReadXML(string yourPath)
{
DataTable table = new DataTable("Item");
try
{
DataSet lstNode = new DataSet();
lstNode.ReadXml(yourPath);
table = lstNode.Tables["Item"];
return table;
}
catch (Exception ex)
{
return table;
}
}
And here's XML format:
<?xml version="1.0" encoding="utf-8" ?>
<db>
<Item>
<Id>222</Id>
<OldCode>ZA</OldCode>
<NewCode>ZAF</NewCode>
<Name>Africa (South )</Name>
</Item>
</db>
Use dataset in place of datatable
Here is a sample-code in Powershell:
$xmlString = #"
<table1>
<row1>
<c1>value1</c1><c2>value2</c2>
</row1>
<row2>
<c1>value3</c1><c2>value4</c2>
</row2>
</table1>
"#
$sr =[System.IO.StringReader]($xmlString)
$dataset =[System.Data.DataSet]::new()
$null = $dataset.ReadXml($sr)
and this is the result of $dataset.tables:
c1 c2
-- --
value1 value2
value3 value4
Dynamic Xml to DataTable
public DataTable XMLToDataTable(string YourFilePath)
{
DataTable table = new DataTable("XMLTABLE");
try
{
#region "'< <> >& NOT VALID EXTENSTION IN XML
var xmlContent = File.ReadAllText(YourFilePath);
XmlDocument xDoc = new XmlDocument();
xDoc.LoadXml(xmlContent.Replace("'", "'").Replace("&", "&"));
xDoc.Save(YourFilePath);
#endregion
//All XML Document Content
//XmlElement root = xDoc.DocumentElement;
string RootNode = xDoc.DocumentElement.Name;
string RootChildNode = xDoc.DocumentElement.LastChild.Name;
DataSet lstNode = new DataSet();
lstNode.ReadXml(YourFilePath);
table = lstNode.Tables[RootChildNode];
return table;
}
catch (Exception ex)
{
}
}
Related
<?xml version="1.0" encoding="utf-8" ?>
<Title>
<subtitle>12,15,1,4 </subtitle>
</Title >
This is my xml structure and I need to split the value and add it to dropdownlist, but I'm getting whole value in dropdownlist, kindly provide me the solution and my code is
private void bindxml()
{
StreamReader str = new StreamReader(filepath);
using (DataSet ds = new DataSet())
{
ds.ReadXml(filepath);
DropDownList1.DataSource = ds;
DropDownList1.DataTextField = "subtitle";
DropDownList1.DataBind();
}
}
DropDownList1.Items.AddRange(XElement.Load(filepath).Element("subtitle").Value
.Split(',').Select(x => new ListItem(x)).ToArray());
Load the XML, navigate to the "subtitle" element, split that value using the comma delimiter and then create a new ListItem for each element. Pass this collection, as an array, to the DropDownList AddRange method.
Use the below code:
string elements = string.Empty;
XmlDocument xml = new XmlDocument();
string xmlFilePath = Server.MapPath("XMLFile1.xml"); //File Name
xml.Load(xmlFilePath);
XmlNodeList companyList = xml.GetElementsByTagName("subtitle");
foreach (XmlNode node in companyList)
{
XmlElement companyElement = (XmlElement)node;
elements = companyElement.InnerText;
}
List<int> subIds = new List<int>();
if (elements!="")
{
subIds = elements.Split(',').Select(int.Parse).ToList();
}
ddlSub.DataSource = TagIds;
ddlSub.DataBind();
ddlSub.Items.Insert(0, new ListItem("--Select Subtitle--", "0"));
I have a problem with the reading an xml, that was created saving the same schema that i used to read.
When I read a DataTable, for example Person, that has one row, the DataTable read the row but show me like all columns where null, when all columns are not null.
The code I use is the following
private DataSet LoadShema(string path)
{
string _archivoXsd = System.AppDomain.CurrentDomain.BaseDirectory +"Scheme.xsd";//HERE IS WHERE THE .XSD FILE IS
DataSet esquemaXSD = new DataSet();
string archivoXml = path;
FileStream FsXSD = new FileStream(_archivoXsd, FileMode.Open);
FileStream FsXML = new FileStream(archivoXml, FileMode.Open);
XmlTextReader xtrXSD = new XmlTextReader(FsXSD);
try
{
esquemaXSD.ReadXmlSchema(xtrXSD);
xtrXSD.Close();
FsXSD.Close();
XmlTextReader xtrXML = new XmlTextReader(FsXML);
esquemaXSD.ReadXml(xtrXML);
xtrXML.Close();
FsXML.Close();
}
catch
{
}
return esquemaXSD;
}
This is how I load the xml in the scheme, then another thing I do is assigning:
_dtPerson = new DataTable();
_dtPerson = esquemaXSD.Tables["Person"];
and for last, what I do is the following:
if (_dtPerson.Rows.Count == 1)
{
string name = Convert.ToString(_dtPerson.Rows[0]["Name"]);
}
and when i do the last code line, an exception that said "Can not convert DBNull object to other types".
DataSet ds = new DataSet();
DataTable dataTable = new DataTable();
ds.ReadXml("File.xml");
dataTable = ds.Tables[0];
LoadListView(dataTable);
<?xml version="1.0"?>
<Book>
<note1>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note1>
</Book>
I am reading whole xml file in dataset and then dispaly all records to Listview.
But when i load all data to listview Memory consumption is more. Datatable takes all memory of my machine and off course at some time gives me an exception out of memory Exception.Is it possible to load datatable after filter.
Above is my xml file having multiple nodes i have to load only those nodes in datatable having XmlElement from starts with 'j'.
I will appreciate for the answers.
I dont want to use XMlDocument or Xpathquery or LINQ to XML
This is based on the quite weak assumption that you know the XML file's structure (i.e. the format is has a stable, uniform structure). Also I don't know what performance improvement this would bring in your case (as more objects are instantiated). But let's give it a try.
class Program
{
static void Main(string[] args)
{
List<string> list = new List<string>();
List<int> positions = new List<int>();
bool checkNext = false;
int position = -1;
DataTable dataTable = new DataTable();
dataTable.Columns.Add("to");
dataTable.Columns.Add("from");
dataTable.Columns.Add("heading");
dataTable.Columns.Add("body");
var rs = new XmlReaderSettings();
rs.IgnoreWhitespace = true;
using (var reader = XmlReader.Create(File.OpenRead("data.xml"), rs))
{
while (reader.Read())
{
if (reader.Name == "")
{
list.Add(reader.Value);
position++;
}
if (checkNext)
{
// TODO: apply your filter
if (reader.Value.ToLower().StartsWith("j"))
{
positions.Add(position);
}
}
if (reader.Name == "from")
{
checkNext = !checkNext;
}
}
}
foreach (int match in positions)
{
dataTable.Rows.Add(
list[match - 1],
list[match],
list[match + 1],
list[match + 2]);
}
//LoadListView(dataTable);
}
}
My XML Example:
<Table diffgr:id="Table17" msdata:rowOrder="16">
<IdRec>17</IdRec>
<FieldId>1213</FieldId>
<FieldDesc>Equipment</FieldDesc>
<FieldType>OptionBOX</FieldType>
<isReadOnly>false</isReadOnly>
<FieldValue>388</FieldValue>
<FieldTextValue>B - satisfactory</FieldTextValue>
<OptBox_Options>
<Options>
<myOPT FieldValue="387" FieldTextValue="A - good"/>
<myOPT FieldValue="388" FieldTextValue="B - satisfactory"/>
<myOPT FieldValue="389" FieldTextValue="C - needs change"/>
<myOPT FieldValue="390" FieldTextValue="D - deal"/>
</Options>
</OptBox_Options>
</Table>
My problem
The above xml data comes from a webservice. I have no problem with any field other than OptBox_Options which is a field I need to use to populate my spinner. Ergo I need to get the string from OptBox_Options->Options->myOpt(FieldTextValue) (for example: ).
How to access this data? What would be the best approach. If you can't give me a direct solution I would be satisfied with a link to noob friendly C# tutorial on the subject.
Isssue Resolved
I transformed my string to XML, then converted it to a dataset and just cycled through it... Code below :)
List<string> entries = new List<string>();
String rawXML = item.OptBox_Options;
StringReader stream = null;
XmlTextReader reader = null;
DataSet xmlDS = new DataSet();
stream = new StringReader(rawXML);
// Load the XmlTextReader from the stream
reader = new XmlTextReader(stream);
xmlDS.ReadXml(reader);
DataSet myOPTvalues = new DataSet();
myOPTvalues = xmlDS;
foreach (DataRow row in myOPTvalues.Tables[0].Rows)
{
var optItem = new PrevzemSpin();
optItem.FieldValue = row["FieldValue"].ToString();
if (optItem.FieldValue.Equals("")) optItem.FieldValue = null;
optItem.FieldTextValue = row["FieldTextValue"].ToString();
if (optItem.FieldTextValue.Equals("")) optItem.FieldTextValue = null;
entries.Add(optItem.FieldTextValue);
SpinnerValue.Tag = optItem.FieldValue;
}
Use xml parsing techniques such as XmlPullParser ,SAX parser or DOM parser.
XML Pull parser is the parser recommended in the developer's site of android Here is a tutorial for Pull parser .
I transformed my string to XML, then converted it to a dataset and just cycled through it... Code below :)
List<string> entries = new List<string>();
String rawXML = item.OptBox_Options;
StringReader stream = null;
XmlTextReader reader = null;
DataSet xmlDS = new DataSet();
stream = new StringReader(rawXML);
// Load the XmlTextReader from the stream
reader = new XmlTextReader(stream);
xmlDS.ReadXml(reader);
DataSet myOPTvalues = new DataSet();
myOPTvalues = xmlDS;
foreach (DataRow row in myOPTvalues.Tables[0].Rows)
{
var optItem = new PrevzemSpin();
optItem.FieldValue = row["FieldValue"].ToString();
if (optItem.FieldValue.Equals("")) optItem.FieldValue = null;
optItem.FieldTextValue = row["FieldTextValue"].ToString();
if (optItem.FieldTextValue.Equals("")) optItem.FieldTextValue = null;
entries.Add(optItem.FieldTextValue);
SpinnerValue.Tag = optItem.FieldValue;
}
I'm trying to read a simple webservice (REST) and populate a drop down box in my C# desktop application. I;m using .net 2.0
Following is my web service return xml
<sections type="array">
<section>
<name>Standing</name>
<created-at type="datetime">2011-10-23T23:17:54+05:30</created-at>
<updated-at type="datetime">2011-10-23T23:17:54+05:30</updated-at>
<id type="integer">1</id>
<status type="integer">1</status>
<service-charge type="float">0.0</service-charge>
</section>
<section>
<name>VIP</name>
<created-at type="datetime">2011-10-30T11:27:05+05:30</created-at>
<updated-at type="datetime">2011-10-30T11:27:05+05:30</updated-at>
<id type="integer">2</id>
<status type="integer">1</status>
<service-charge type="float">10.0</service-charge>
</section>
and in the following code I'm trying to convert the xml document to a data table
public DataTable getSections() {
String url = "http://<site_url>/sections.xml";
DataTable t = new DataTable();
HttpHandler handle = new HttpHandler();
StreamReader sr = handle.executeGET(url);
String xml = "";
while (sr.Peek() >= 0)
{
xml += sr.ReadLine();
}
XmlDataDocument doc = new XmlDataDocument();
doc.LoadXml(xml);
XmlReader xmlReader = new XmlNodeReader(doc);
DataSet ds = new DataSet();
ds.ReadXml(xmlReader);
t = ds.Tables[0];
return t;
}
and in the last segment I'm trying to bind it to my drop down box (cmbSections)
DataTable t = sec.getSections();
cmbSections.DataSource = t;
cmbSections.DisplayMember = "name";
cmbSections.ValueMember = "id";
But I'm getting the following error
Cannot bind to the new display member.
Parameter name: newDisplayMember
What am i missing here, please help, I'm new to C# world
Use extension method to support conversion of XElement to Datatable. You can add this method to any of your utility classes. Make sure the class is static.
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));
}
}
How to use
//Add logic to store xml data in file or string & read accordingly here.
string file = Server.MapPath("~/Data.xml");
XDocument document = XDocument.Load(file);
var query = from b in document.Elements("sections").Elements("section")
select b;
DataTable table = query.ToDataTable();
Simple way to convert XML to DataSet:
StringReader strr = new StringReader(strXML);
XmlTextReader xtr = new XmlTextReader(strr);
YourTypeDataSet dstest = new YourTypeDataSet();
dstest.ReadXml(xtr);
if (dstest.Tables.Count > 0) ...
for correct conversion, you replace your type DataSet in place of:
DataSet dstest = new DataSet();
;)
I got it working with the following code, but I'm not quit sure if this is the correct way to do it
(This parse the above same xml)
public DataTable getSections() {
String url = "http://<site_url>/sections.xml/sections.xml";
DataTable t = new DataTable();
t.Columns.Add("id", typeof(String));
t.Columns.Add("name", typeof(String));
HttpHandler handle = new HttpHandler();
StreamReader sr = handle.executeGET(url);
String xml = "";
List<String> id = new List<string>();
List<String> name = new List<string>();
while (sr.Peek() >= 0)
{
xml += sr.ReadLine();
}
XmlDataDocument doc = new XmlDataDocument();
doc.LoadXml(xml);
XmlReader xmlReader = new XmlNodeReader(doc);
while (xmlReader.Read()){
if (xmlReader.IsStartElement()) {
String b = xmlReader.Name;
switch (xmlReader.Name) {
case "sections":
break;
case "section":
break;
case "id":
if (xmlReader.Read())
{
id.Add(xmlReader.Value.Trim());
}
break;
case "name":
if (xmlReader.Read())
{
name.Add(xmlReader.Value.Trim());
}
break;
}
}
}
int counter = 0;
foreach (String i in id) {
DataRow r = t.NewRow();
r["id"] = i;
r["name"] = name[counter];
t.Rows.Add(r);
counter += 1;
}
return t;
}
Thanks for the comments :D
Your valuable comments are always welcome