Reading XML with Schema XSD - c#

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

Related

From EXCEL to XSD generated class in C#

I have this situation, I have been provided with an XSD schema consisting of four XSD files which I was able to convert to a class using the XSD.exe tool and include it in my project, for this example this class is named "Test_XSD". On the other side I have a populated excel sheet table consisting of 10 columns which I need to map to certain elements in the "Text XSD". The "Test_XSD" schema is complex however if I map the 10 columns to their relevant elements is sufficient since many other elements are not mandatory. I have searched and searched but cannot find a simple example to start building on it.
I am able to read the excel file in Visual Studio and convert to XML, however this does not conform with the XSD generated class. I know that I have to create an instance of the "Test_XSD" and load it with the data from the Excel but I don't have any clue from where to start. Can someone explain what needs to be done.
This is what I've done so far, not too much I admit but this is something totally new for me and to be honest I didn't have yet understood the way forward although I've researched a lot.
static void Main(string[] args)
{
// Using an OleDbConnection to connect to excel
var cs = $#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source={#"C:\AAAA\Report.xlsx"};Extended Properties=""Excel 12.0 Xml; HDR = Yes; IMEX = 2"";Persist Security Info=False";
var con = new OleDbConnection(cs);
con.Open();
// Using OleDbCommand to read data of the sheet(sheetName)
var cmd = new OleDbCommand($"select * from [Sheet1$]", con);
var ds = new DataSet();
var da = new OleDbDataAdapter(cmd);
da.Fill(ds);
//// Convert DataSet to Xml
//using (var fs = new FileStream(#"C:\Users\MT2362\Downloads\CRS_XML.xml", FileMode.CreateNew))
//{
// using (var xw = new XmlTextWriter(fs, Encoding.UTF8))
// {
// ds.WriteXml(xw);
// }
//}
XSD xsd = new XSD();
xsd.version = "TEST VERSION";
Console.WriteLine(xsd.version);
Console.ReadKey();
}
I've noted taht the class generated from the XSD ("Test_XSD") is composed of multiple partial class, hence I think that an instance for each class must be created.
Thanks in advance, code snippets are highly appreciated.
The object of your XSD class would have public properties. If you set the value of these properties (similar to your .version in your example), then your object is fully populated.
Is this what you want ?
After running the XSD.exe tool, the output would be a list of C# classes that would be available to you.
Since you were able to successfully read from the Excel file and create and XML file for the dataset.
Perform the following:
Add a new class to your project as follows:
public class ExcelNameSpaceXmlTextReader : XmlTextReader
{
public ExcelNameSpaceXmlTextReader(System.IO.TextReader reader)
: base(reader) { }
public override string NamespaceURI
{
get { return ""; }
}
}
Then in a separate Utitlity class add a deserializer function as follows
public class Utility
{
public T FromXml<T>(String xml)
{
T returnedXmlClass = default(T);
using (TextReader reader = new StringReader(xml))
{
returnedXmlClass = (T)new XmlSerializer(typeof(T)).Deserialize(new ExcelNameSpaceXmlTextReader(reader));
}
return returnedXmlClass;
}
}
Now add code to consume the read in data from XML as the object you want to serialize the data to by consuming the generic Utility function
So your code would be like
static void Main(string[] args)
{
// Using an OleDbConnection to connect to excel
var cs = $#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source={#"C:\AAAA\Report.xlsx"};Extended Properties=""Excel 12.0 Xml; HDR = Yes; IMEX = 2"";Persist Security Info=False";
var con = new OleDbConnection(cs);
con.Open();
// Using OleDbCommand to read data of the sheet(sheetName)
var cmd = new OleDbCommand($"select * from [Sheet1$]", con);
var ds = new DataSet();
var da = new OleDbDataAdapter(cmd);
da.Fill(ds);
// Convert DataSet to Xml
using (var fs = new FileStream(#"C:\Users\MT2362\Downloads\CRS_XML.xml", FileMode.CreateNew))
{
using (var xw = new XmlTextWriter(fs, Encoding.UTF8))
{
ds.WriteXml(xw);
}
}
XDocument doc = XDocument.Load("C:\Users\MT2362\Downloads\CRS_XML.xml");
Test_XSD test_XSD = Utility.FromXml<Test_XSD>(doc.Document.ToString());
XSD xsd = new XSD();
xsd.version = "TEST VERSION";
Console.WriteLine(xsd.version);
Console.ReadKey();
}

Mono for Android: XML data to spinner

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;
}

converting xml document to data table in C#

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

Read in xls file as well as current csv file in app

I have the following code -
private void button1_Click(object sender, EventArgs e)
{
string csv = File.ReadAllText("FilePath");
WebService.function res = new WebService.function();
XDocument doc = ConvertCsvToXML(csv, new[] { "," });
I was wondering how a could adjust the code so that it not only reads .csv files but also .xls files?
I created a public XDocument to do this -
public XDocument ConvertCsvToXML(string csvString, string[] separatorField)
{
var sep = new[] { "\n" };
string[] rows = csvString.Split(sep, StringSplitOptions.RemoveEmptyEntries);
var xsurvey = new XDocument(
new XDeclaration("1.0", "UTF-8", "yes"));
var xroot = new XElement("details");
If I understand your question correctly, you are looking to parse an excel file as text in the same manner that you parse the csv file. While this is possible, you should consider using Office Interop interfaces to do this. If you want to parse the raw file you'll need to account for the different formats between Office versions and a whole slew of encoding/serialization tasks; no small task.
Here are some resources to get you started:
Reading Excel from C#
How to Automate Excel from C#
I'm not sure from your question...but if you are asking how to read an excel file in c#, this will work:
string fileName = [insert path and name];
string connectionString = string.Format("Provider=Microsoft.Jet.OLEDB.4.0;data source={0}; Extended Properties=Excel 8.0;", fileName); // Create the data adapter pointing to the spreadsheet
var oa = new OleDbDataAdapter("SELECT * FROM [xxx$]", connectionString); // xxx is tab name
// Create a blank data set
var ds = new DataSet(); // Fill the data set using the adapter
oa.Fill(ds, "table1"); // Create a data table from the data set
DataTable dt1 = ds.Tables["table1"];
foreach (DataRow dr in dt1.Rows)
{
...
}

How to read XML into a DataTable?

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 "&apos;< <> >&amp NOT VALID EXTENSTION IN XML
var xmlContent = File.ReadAllText(YourFilePath);
XmlDocument xDoc = new XmlDocument();
xDoc.LoadXml(xmlContent.Replace("'", "&apos;").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)
{
}
}

Categories