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
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"));
Ive got an asp.net page in which im using c# to read an xml document and add each entry into a listview.
I then have the function for the user to add a new entry to the list view but i cant figure out how to save it on a button event.
This is what I have to load the document.
protected void Button6_Click(object sender, EventArgs e)
{
XmlDocument xmlDocument = new XmlDocument();
using (DataTable tabListView1 = new DataTable())
{
tabListView1.Columns.Add("value", Type.GetType("System.String"));
xmlDocument.Load(AppDomain.CurrentDomain.BaseDirectory + "/XmlFile/ListView1.xml");
XmlNodeList xmlNodeList = xmlDocument.SelectNodes("root/data[#open='1']");
foreach (XmlNode xmlNode in xmlNodeList)
{
DataRow dr = tabListView1.NewRow();
dr["value"] = xmlNode.InnerText;
tabListView1.Rows.Add(dr);
}
ListView1.DataSource = tabListView1;
ListView1.DataBind();
}
TextBox3.Text = "Microsoft";
}
How can i make it save changes back to ListView1.xml? Thanks!
Assuming you can get your datasource back as a DataTable from the control you are managing it with, this should help.
private static void SaveXml(string pathAndFileName, DataTable source)
{
XmlDocument xmlDoc = new XmlDocument();
var root = xmlDoc.CreateElement("root");
xmlDoc.AppendChild(root);
foreach (DataRow row in source.Rows)
{
var dataElement = xmlDoc.CreateElement("data");
var openAttribute = xmlDoc.CreateAttribute("open");
openAttribute.Value = "1";
dataElement.Attributes.Append(openAttribute);
dataElement.InnerText = row["value"].ToString();
root.AppendChild(dataElement);
}
xmlDoc.Save(pathAndFileName);
}
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;
}
Q :
According to some choices of the user, i will get set of Datatables from the database.
i have three datatabels:Teachers,Subjects,ClassRooms
and I want an xml file with the following structure:
<timetable importtype="database" options="idprefix:id">
<teachers options="" columns="id,name,short">
</teachers>
<subjects options="" columns="id,name,short">
</subjects>
<classrooms options="" columns="id,name,short">
</classrooms>
</timetable>
Now How to generate xml file with the previous structure and fill the xml file data from the data tables?
ex:
<teachers options="" columns="id,name,short">
<teacher id="a" name="jhon" short="jo"/>
<teacher id="b" name="philips" short="Ph"/>
<teacher id="c" name="sara" short="Sa"/>
</teachers>
From teacher datatable.
please details answer with sample example as possible.
EDIT :
private static void ConvertDataTableToXML(string schemaFile, DataTable dtTeacher, DataTable dtSubject, DataTable dtClassRoom)
{
XDocument doc = new XDocument();
//Read the teachers element from xml schema file
XElement teachers = XDocument.Load(schemaFile).Descendants("teachers").SingleOrDefault();
XElement subjects = XDocument.Load(schemaFile).Descendants("subjects").SingleOrDefault();
XElement classes = XDocument.Load(schemaFile).Descendants("classrooms").SingleOrDefault();
if (teachers != null)
{
foreach (DataRow row in dtTeacher.Rows)
{
XElement teacher = new XElement("teacher");
teacher.SetAttributeValue("id", row["id"]);
teacher.SetAttributeValue("name", row["name"]);
teacher.SetAttributeValue("short", row["name"].ToString().Substring(0, 2));
teachers.Add(teacher);
}
}
if (subjects != null)
{
foreach (DataRow row in dtSubject.Rows)
{
XElement subject = new XElement("subject");
subject.SetAttributeValue("id", row["num"]);
subject.SetAttributeValue("name", row["name"]);
subject.SetAttributeValue("short", row["name"].ToString().Substring(0, 2));
subjects.Add(subject);
}
}
if (classes != null)
{
foreach (DataRow row in dtClassRoom.Rows)
{
XElement cls = new XElement("classroom");
cls.SetAttributeValue("id", row["id"]);
cls.SetAttributeValue("name", row["name"]);
cls.SetAttributeValue("short", row["name"].ToString().Substring(0, 2));
classes.Add(cls);
}
}
XElement xml = new XElement("timetable",
new XAttribute("importtype", "database"),
new XAttribute("options", "idprefix:id"),teachers,subjects,classes
);
doc.Add(xml);
string dirPath = System.Web.HttpContext.Current.Server.MapPath("~/import");
string targetFileName = Path.Combine(dirPath, "import.xml");
int counter = 1;
while (System.IO.File.Exists(targetFileName))
{
counter++;
targetFileName = Path.Combine(dirPath,
"import" + counter.ToString() + ".xml");
}
doc.Save(targetFileName);
}
You may try to read and update XML document using Linq-XML.
Have a look at sample:
//Read the teachers element from xml schema file
XElement teachers = XDocument.Load(schemaFile).Descendants("teachers").SingleOrDefault();
if (teachers != null)
{
DataTable dt = new DataTable();
dt.Columns.Add("id");
dt.Columns.Add("name");
dt.Rows.Add("1", "john");
dt.Rows.Add("2", "philips");
dt.Rows.Add("3", "sara");
XDocument doc = new XDocument();
foreach (DataRow row in dt.Rows)
{
XElement teacher = new XElement("teacher");
teacher.SetAttributeValue("id", row["id"]);
teacher.SetAttributeValue("name", row["name"]);
teacher.SetAttributeValue("short", row["name"].ToString().Substring(0,2));
teachers.Add(teacher);
}
doc.Add(teachers);
doc.Save(newFilename);
}