This code is programmed to display some data values from alot of xml files is their anyway to alter it so that it write the values to a dataset/table?
static void Main(string[] args)
{
string[] fileEntries = Directory.GetFiles(#"c:\Sciclone UAC", "*.cfg*");
foreach (string fileName in fileEntries)
{
XDocument doc = XDocument.Load(fileName);
var query = from x in doc.Descendants("XAxisCalib")
select new
{
//Max1 = x.Attribute("Max").Value,
//Min2 = x.Attribute("Min").Value
MaxChild = x.Descendants("Max"),
MinChild = x.Descendants("Min")
};
foreach (var x in query)
{
foreach (var nextLevel in x.MaxChild)
{
Console.WriteLine("XMax: " + nextLevel.Value);
}
foreach (var nextLevel in x.MinChild)
{
Console.WriteLine("XMin: " + nextLevel.Value);
}
//Console.WriteLine("XAxisCalib");
}
var query2 = from y in doc.Descendants("YAxisCalib")
select new
{
//Max3 = x.Attribute("Max").Value,
//Min4 = x.Attribute("Min").Value
MaxChild = y.Descendants("Max"),
MinChild = y.Descendants("Min")
};
foreach (var y in query2)
{
foreach (var nextLevel in y.MaxChild)
{
Console.WriteLine("YMax: " + nextLevel.Value);
}
foreach (var nextLevel in y.MinChild)
{
Console.WriteLine("YMin: " + nextLevel.Value);
}
//Console.WriteLine("YAxisCalib");
var query3 = from z in doc.Descendants("ZAxisCalib")
select new
{
//Max5 = x.Attribute("Max").Value,
//Min6 = x.Attribute("Min").Value
MaxChild = z.Descendants("Max"),
MinChild = z.Descendants("Min")
};
foreach (var z in query3)
{
foreach (var nextLevel in z.MaxChild)
{
Console.WriteLine("ZMax: " + nextLevel.Value);
}
foreach (var nextLevel in z.MinChild)
{
Console.WriteLine("ZMin: " + nextLevel.Value);
}
//Console.WriteLine("ZAxisCalib");
}
}
}
}
}
}
I don't know if I'm missing something, but what about the DataSet.ReadXml method?:
DataSet ds = new DataSet();
ds.ReadXml("myxmlfile.xml");
The ReadXml() method has an overload for passing in XmlReadMode, which provides various options handling the schema.
In your case, assuming that you want to read each XML file into it's own DataSet, you can do something like this:
string[] fileEntries = Directory.GetFiles(#"c:\Sciclone UAC", "*.cfg*");
foreach (string fileName in fileEntries)
{
DataSet ds = new DataSet();
ds.ReadXml(fileName, XmlReadMode.InferSchema);
}
To read the XML files into the same DataSet, you can do something like this:
DataSet masterSet = new DataSet();
string[] fileEntries = Directory.GetFiles(#"c:\Sciclone UAC", "*.cfg*");
foreach (string fileName in fileEntries)
{
//initialize a new dataset and read the xml into it
DataSet tempSet = new DataSet();
tempSet.ReadXml(fileName, XmlReadMode.InferSchema);
//merge the tables from the temporary datset into the master dataset
foreach (DataTable table in tempSet.Tables)
masterSet.Merge(table);
}
Here's another way of doing the same thing, using the enumerable LINQ methods:
DataSet masterSet = new DataSet();
string[] fileEntries = Directory.GetFiles(#"c:\Sciclone UAC", "*.cfg*");
foreach (string fileName in fileEntries)
{
//initialize a new dataset and read the xml into it
DataSet tempSet = new DataSet();
tempSet.ReadXml(fileName, XmlReadMode.InferSchema);
//merge the tables from the temporary datset into the master dataset
tempSet.Tables.Cast<DataTable>().ToList().ForEach(table => masterSet.Merge(table));
}
One of the XmlReadMode enumerations should definitely suit your needs.
Auto
DiffGram
Fragment
IgnoreSchema
InferSchema
InferTypedSchema
ReadSchema
Here is a link on MSDN that explains what the different XmlReadMode enumerations do:
http://msdn.microsoft.com/en-us/library/system.data.xmlreadmode.aspx
Related
The data is not displayed correctly in the columns.
The CSV consists of 7 columns. Rows are of different length.
I can not upload a picture.(https://ibb.co/0fnfLW7)
DataTable tblcsv = new DataTable();
tblcsv.Columns.Add("Vorname");
tblcsv.Columns.Add("Nachname");
tblcsv.Columns.Add("RFID");
string csvData = File.ReadAllText(csvPath);
//spliting row after new line
foreach (string csvRow in csvData.Split(';'))
{
if (!string.IsNullOrEmpty(csvRow))
{
//Adding each row into datatable
tblcsv.Rows.Add();
int count = 0;
foreach (string FileRec in csvRow.Split(';'))
{
tblcsv.Rows[tblcsv.Rows.Count - 1][count] = FileRec;
count++;
for(var x=0; x<7; x++)
{
//tblcsv[x][count] = FileRec;
}
count++;
}
}
//Calling Bind Grid Functions
BindgridStaffImport(tblcsv);
}
You split code is using ";", and should it not be "," if a csv?
The code will look much like this:
foreach (string csvRow in csvData.Split(';'))
{
if (!string.IsNullOrEmpty(csvRow))
{
//Adding each row into datatable
DataRow MyNewRow = tblcsv.NewRow();
int count = 0;
foreach (string FileRec in csvRow.Split(','))
{
MyNewRow[count] = FileRec;
count++;
}
tblcsv.Rows.Add(MyNewRow);
}
//Calling Bind Grid Functions
BindgridStaffImport(tblcsv);
So, use the "newRow" method to create a new blank row based on the table. Set the column values, and then add this new row to the rows collection of the table.
And even better is to use the TextFieldParser class.
So,
using Microsoft.VisualBasic.FileIO;
And then you can even assume say the first row has the colum names.
This:
We assume you read the csv file into stirng sFileLocal
// process csv file
TextFieldParser MyParse = new TextFieldParser(sFileLocal);
MyParse.TextFieldType = FieldType.Delimited;
MyParse.SetDelimiters(new string[] { "," });
MyParse.HasFieldsEnclosedInQuotes = true;
// add colums to table.
DataTable rstData = new DataTable();
foreach (string cCol in MyParse.ReadFields())
{
rstData.Columns.Add(cCol);
}
while (!MyParse.EndOfData)
{
string[] OneRow = MyParse.ReadFields();
rstData.Rows.Add(OneRow);
}
// Now display results in a grid
GridView1.DataSource = rstData;
GridView1.DataBind();
Quite much all above is you need.
Thank you very much for the support.
I now have a working variant.
However, the goal is to skip the first line, the header.
Are there any ideas how I can implement this.
List<string> headercolumns = new List<string> { "Vorname", "Nachname", };
DataTable dt = new DataTable();
foreach (string header in headercolumns)
{
dt.Columns.Add(header);
}
List<string> StaffList = new List<string>();
using (StreamReader filereader = new StreamReader(StaffFileUpload.FileContent))
{
string readline = string.Empty;
while ((readline = filereader.ReadLine()) != null)
{
StaffList.Add(readline);
}
if (StaffList != null && StaffList.Count > 0)
{
foreach (string info in StaffList)
{
DataRow row = dt.NewRow();
string[] mitarbeiter = info.Split(';');
for (int i = 0; i < mitarbeiter.Length; i++)
{
row[i] = mitarbeiter[i];
}
dt.Rows.Add(row);
}
}
}
I have a program to parse a CSV file from local filesystem to a specified SQL Server table.
Now when i execute the program i get error :
System.IndexOutOfRangeException: 'Cannot find column 1' exception on the line where i the program attempts to populate the datatable.
On closer inspection the error shows that its emanating from row number 3 as shown on this link :
CSV_ERROR
This is how i am reading and saving the CSV file :
static void Main(string[] args)
{
var absPath = #"C:\Users\user\Documents\Projects\MastercardSurveillance\fbc_mc_all_cards.csv";
ProcessFile();
void ProcessFile()
{
string realPath = #"C:\Users\user\Documents\CSV";
string appLog = "CSVERRORS";
var logPath = realPath + Convert.ToString(appLog) + DateTime.Today.ToString("dd -MM-yy") + ".txt";
if (!File.Exists(logPath))
{
File.Create(logPath).Dispose();
}
var dt = GetDATATable();
if (dt == null)
{
return;
}
if (dt.Rows.Count == 0)
{
using (StreamWriter sw = File.AppendText(logPath))
{
sw.WriteLine("No rows imported after reading file " + absPath);
sw.Flush();
sw.Close();
}
return;
}
ClearData();
InsertDATA();
}
DataTable GetDATATable()
{
var FilePath = absPath;
string TableName = "Cards";
string realPath = #"C:\Users\user\Documents\CSV";
string appLog = "CSVERRORS";
var logPath = realPath + Convert.ToString(appLog) + DateTime.Today.ToString("dd -MM-yy") + ".txt";
if (!File.Exists(logPath))
{
File.Create(logPath).Dispose();
}
var dt = new DataTable(TableName);
using (var csvReader = new TextFieldParser(FilePath))
{
csvReader.SetDelimiters(new string[] { "," });
csvReader.HasFieldsEnclosedInQuotes = true;
var readFields = csvReader.ReadFields();
if (readFields == null)
{
using (StreamWriter sw = File.AppendText(logPath))
{
sw.WriteLine("Could not read header fields for file " + FilePath);
sw.Flush();
sw.Close();
}
return null;
}
foreach (var dataColumn in readFields.Select(column => new DataColumn(column, typeof(string)) { AllowDBNull = true, DefaultValue = string.Empty }))
{
dt.Columns.Add(dataColumn);
}
while (!csvReader.EndOfData)
{
var data = csvReader.ReadFields();
if (data == null)
{
using (StreamWriter sw = File.AppendText(logPath))
{
sw.WriteLine(string.Format("Could not read fields on line {0} for file {1}", csvReader.LineNumber, FilePath));
sw.Flush();
sw.Close();
}
continue;
}
var dr = dt.NewRow();
for (var i = 0; i < data.Length; i++)
{
if (!string.IsNullOrEmpty(data[i]))
{
dr[i] = data[i];
}
}
dt.Rows.Add(dr);
}
}
return dt;
}
void ClearData()
{
string SqlSvrConn = #"Server=XXXXXX-5QFK4BL\MSDEVOPS;Database=McardSurveillance;Trusted_Connection=True;MultipleActiveResultSets=true;";
using (var sqlConnection = new SqlConnection(SqlSvrConn))
{
sqlConnection.Open();
// Truncate the live table
using (var sqlCommand = new SqlCommand(_truncateLiveTableCommandText, sqlConnection))
{
sqlCommand.ExecuteNonQuery();
}
}
}
void InsertDATA()
{
string SqlSvrConn = #"Server=XXXXXX-5QFK4BL\MSDEVOPS;Database=McardSurveillance;Trusted_Connection=True;MultipleActiveResultSets=true;";
DataTable table = GetDATATable();
using (var sqlBulkCopy = new SqlBulkCopy(SqlSvrConn))
{
sqlBulkCopy.DestinationTableName = "dbo.Cards";
for (var count = 0; count < table.Columns.Count; count++)
{
sqlBulkCopy.ColumnMappings.Add(count, count);
}
sqlBulkCopy.WriteToServer(table);
}
}
}
How can i identify and possibly exclude the extra data columns being returned from the CSV file?
It appears there is a mismatch between number of columns in datatable and number of columns being read from the CSV file.
Im not sure however how i can account for this with my logic. For now i did not want to switch to using a CSV parse package but rather i need insight on how i can remove the extra column or rather ensure that the splitting takes account of all possible dubious characters.
For clarity i have a copy of the CSV file here :
CSV_FILE
I have a csv file in the same project with a Build Action of "Embedded Resource". When I try to create a stream using this file I get the following error:
system.io.stream.null.readtimeout threw an exception of type system.invalidoperationexception
When I let it run I catch an exception that says:
Value cannot be null.\r\nParameter name: stream
I am not sure what is causing this? Is it possible that it's not picking up my file for some reason and therefore nothing gets passed into the stream?
internal static void InsertPropertyDefinitions()
{
DataTable csvData = null;
string[] columnNames = null;
int rowCount = 0;
string[] streamDataValues = null;
try {
using (Stream stream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(
"My csv file path"))
{
StreamReader streamReader = new StreamReader(stream);
while (!streamReader.EndOfStream)
{
String streamRowData = streamReader.ReadLine().Trim();
if (streamRowData.Length > 0)
{
streamDataValues = streamRowData.Split(',');
if (rowCount == 0)
{
rowCount = 1;
columnNames = streamRowData.Split(',');
csvData = new DataTable();
foreach (string csvColumn in columnNames)
{
DataColumn dataColumn = new DataColumn(csvColumn.ToUpper(), typeof(string));
dataColumn.DefaultValue = string.Empty;
csvData.Columns.Add(dataColumn);
}
}
else
{
DataRow dataRow = csvData.NewRow();
for (int i = 0; i < columnNames.Length; i++)
{
dataRow[columnNames[i]] = streamDataValues[i] == null ? string.Empty : streamDataValues[i].ToString();
}
csvData.Rows.Add(dataRow);
}
}
}
streamReader.Close();
streamReader.Dispose();
foreach (DataRow dataRow in csvData.Rows)
{
string rowValues = string.Empty;
foreach (string csvColumn in columnNames)
{
rowValues += csvColumn + "=" + dataRow[csvColumn].ToString() + "; ";
}
}
}
}
Try by resourceName :
var assembly = Assembly.GetExecutingAssembly();
var resourceName = "MyCompany.MyProduct.MyFile.csv";
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
using (StreamReader reader = new StreamReader(stream))
{
...
}
The resource name is not necessarily equal to the name of the file. You can check using Assembly.GetManifestResourceNames();
Usually VS add namespace to resource name. Then MyList.csv -> NS.MyList.csv
To get names
var assembly = System.Reflection.Assembly.GetExecutingAssembly();
var lst = assembly.GetManifestResourceNames();
Console.WriteLine("Files");
Console.WriteLine(string.Join(", ", lst));
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);
}
I have some problems getting the data that i read from XML split into seperate columns. Any help this new C# coder would get would be appreciated.
XDocument xmlDoc = XDocument.Load("emails.xml");
var t = from c in xmlDoc.Descendants("dt")
select (string)c.Element("name") + (string)c.Element("email");
foreach (string item in t)
{
listView.Items.Add(item);
}
XDocument xmlDoc = XDocument.Load("emails.xml");
var t = from c in xmlDoc.Descendants("dt")
select new
{
Name = e.Element("name").Value,
EMail = e.Element("email").Value,
};
foreach (var item in t)
{
var lvi = listView.Items.Add(item.Name);
lvi.SubItems.Add(item.EMail);
}