Here is a piece of code:
XNamespace z = "#SomeSchema";
var listCols = new HashSet<Col>();
var colNameList = new List<string>(..some values..);
var xElementList = doc.Descendants(z + "row");
return new HashSet<Row>(xElementList .Select(x=> new Row
{
Col= new List<Col>(listCols).Select(col =>
{
col.Value= (string)x.Attribute(colNameList.First(colName=> colName == col.Name));
return col;
}).ToList()
}));
What is wrong is that, the return value contains a List of Row, but all of these rows have the exact same value (for the Col Value).
Ex, Row[1].Col[1].Value == Row[2].Col[2].Value
And these values should be completly different. I am obtaining those values from an Xml file. When I debug the xElementList, values are différents, but when I try to create rows with them, all rows are the same.
Actually, the Rows have the same Columns list, which is the last record of the xElementList.
Am I doing something wrong?
Thank you.
See code below. I read the xml twice. Once to get the columns names and add columns to table. Then read xml 2nd time to get row data.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.IO;
using System.Data;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
DataTable dt = new DataTable();
StreamReader sReader = new StreamReader(FILENAME, Encoding.GetEncoding(1252));
XmlReader reader = XmlReader.Create(sReader);
Dictionary<string, string> colDict = new Dictionary<string, string>();
while (!reader.EOF)
{
if (reader.Name != "FIELD")
{
reader.ReadToFollowing("FIELD");
}
if (!reader.EOF)
{
XElement field = (XElement)XElement.ReadFrom(reader);
string attrname = (string)field.Attribute("attrname");
string fieldtype = (string)field.Attribute("fieldtype");
switch (fieldtype)
{
case "string":
dt.Columns.Add(attrname, typeof(string));
break;
case "i4":
dt.Columns.Add(attrname, typeof(int));
break;
}
colDict.Add(attrname, fieldtype);
}
}
reader.Close();
sReader = new StreamReader(FILENAME, Encoding.GetEncoding(1252));
reader = XmlReader.Create(sReader);
while (!reader.EOF)
{
if (reader.Name != "ROW")
{
reader.ReadToFollowing("ROW");
}
if (!reader.EOF)
{
XElement row = (XElement)XElement.ReadFrom(reader);
DataRow newRow = dt.Rows.Add();
foreach (XAttribute attrib in row.Attributes())
{
string colName = attrib.Name.LocalName;
if (colDict.ContainsKey(colName))
{
switch (colDict[colName])
{
case "string":
newRow[colName] = (string)attrib;
break;
case "i4":
newRow[colName] = (int)attrib;
break;
}
}
}
}
}
}
}
}
Related
I have xml like below. Here allowedSessionType can be multiple value sometime. Could anyone help me to read both and store it into data table c# gridview.
I tried but getting single value
<sessionManagementSubscriptionData>
<singleNssai>1-000001</singleNssai>
<dnnConfiguration>
<pduSessionTypes>
<defaultSessionType>IPV4</defaultSessionType>
<allowedSessionType>IPV4</allowedSessionType>
</pduSessionTypes>
<sscModes>
<defaultSscMode>SSC_MODE_1</defaultSscMode>
<allowedSscMode>SSC_MODE_1</allowedSscMode>
</sscModes>
</dnnConfiguration>
<dnnConfiguration>
<pduSessionTypes>
<defaultSessionType>IPV4</defaultSessionType>
<allowedSessionType>IPV4</allowedSessionType>
<allowedSessionType>IPV6</allowedSessionType>
</pduSessionTypes>
<sscModes>
<defaultSscMode>SSC_MODE_1</defaultSscMode>
<allowedSscMode>SSC_MODE_1</allowedSscMode>
</sscModes>
</dnnConfiguration>
</sessionManagementSubscriptionData>
DataTable dt1 = new DataTable();
dt1.Columns.Add("Allowed Session Type", typeof(string));
XmlNodeList nodeList1 = doc.SelectNodes("//sessionManagementSubscriptionData/dnnConfiguration");
foreach (XmlNode node1 in nodeList1)
{
DataRow dtrow1 = dt1.NewRow();
var SMSDDefaultSessionType = node1.SelectSingleNode("//defaultSessionType").InnerText;
dtrow1["Default Session Type"] = SMSDDefaultSessionType;
var SMSDallowedSessionType = node1.SelectSingleNode("//allowedSessionType").InnerText;
dtrow1["Allowed Session Type"] = SMSDallowedSessionType;
dt1.Rows.Add(dtrow1);
}
GridView2.DataSource = dt1;
GridView2.DataBind();
using System.Xml.Serialization;
XmlSerializer serializer = new XmlSerializer(typeof(SessionManagementSubscriptionData));
using (StringReader reader = new StringReader(xml))
{
var test = (SessionManagementSubscriptionData)serializer.Deserialize(reader);
//test.DnnConfiguration has your data
}
[XmlRoot(ElementName="pduSessionTypes")]
public class PduSessionTypes {
[XmlElement(ElementName="allowedSessionType")]
public List<string> AllowedSessionType;
}
[XmlRoot(ElementName="sscModes")]
public class SscModes {
[XmlElement(ElementName="defaultSscMode")]
public string DefaultSscMode;
[XmlElement(ElementName="allowedSscMode")]
public string AllowedSscMode;
}
[XmlRoot(ElementName="dnnConfiguration")]
public class DnnConfiguration {
[XmlElement(ElementName="pduSessionTypes")]
public PduSessionTypes PduSessionTypes;
[XmlElement(ElementName="sscModes")]
public SscModes SscModes;
}
[XmlRoot(ElementName="sessionManagementSubscriptionData")]
public class SessionManagementSubscriptionData {
[XmlElement(ElementName="singleNssai")]
public DateTime SingleNssai;
[XmlElement(ElementName="dnnConfiguration")]
public List<DnnConfiguration> DnnConfiguration;
}
Use this webiste to convert xml to c#
Here is results in a DataTable using Xml Linq
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication11
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
DataTable dt = new DataTable();
dt.Columns.Add("Default Session Type", typeof(string));
dt.Columns.Add("Allowed Session Type", typeof(string));
dt.Columns.Add("Default SSC Mode", typeof(string));
dt.Columns.Add("Allowed SSC Mode", typeof(string));
XDocument doc = XDocument.Load(FILENAME);
foreach (XElement dnnConfiguration in doc.Descendants("dnnConfiguration"))
{
string defaultSessionType = (string)dnnConfiguration.Descendants("defaultSessionType").FirstOrDefault();
string[] allowedSessionType = dnnConfiguration.Descendants("allowedSessionType").Select(x => (string)x).ToArray();
string defaultSscMode = (string)dnnConfiguration.Descendants("defaultSscMode").FirstOrDefault();
string[] allowedSscMode = dnnConfiguration.Descendants("allowedSscMode").Select(x => (string)x).ToArray();
dt.Rows.Add(new object[] { defaultSessionType, string.Join(",", allowedSessionType), defaultSscMode, string.Join(",", allowedSscMode) });
}
}
}
}
I am trying to perform Data driven testing by loading client codes from Excel file to login and perform other operation.I am trying to iterate my test for all clients in the User_Name column. I only need to read Data From SheetName, right now i have Contstant SheetName (i,e sheet1), wanted to add SheetName Parameter
Any help with this would be much appreciated thank you.
I am using ExcelDataReader v3.4.0, ExcelDataReader.DataSet v3.4.0, selenium Webdriver v3.11.0
My Excel Generic Code is Below:
```
using ExcelDataReader;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Threading.Tasks;
namespace MyDemoAutomation
{
public class ExcelUtil
{
public DataTable ExcelToDatable(string fileName)
{
// open file and returns as stream
FileStream stream = File.Open(fileName, FileMode.Open, FileAccess.Read);
// create openXmlReader via ExcelReaderFactory
IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream);
//Set the first row as column name
var result1 = excelReader.AsDataSet(new ExcelDataSetConfiguration()
{
ConfigureDataTable = (_) => new ExcelDataTableConfiguration()
{
UseHeaderRow = true
}
});
// Return as dataset
DataSet result = excelReader.AsDataSet();
// Get all tables
DataTableCollection table = result.Tables;
// Store in Database
DataTable resultTable = table["Sheet1"];
Here instead Sheet 1 i Want to Pass SheetName as Parameter(In Existing Code How can i Add
// return
return resultTable;
}
List<DataCollection> dataCol = new List<DataCollection>();
public void PopulateInCollection(string fileName)
{
DataTable table = ExcelToDatable(fileName);
for (int row = 1; row <= table.Rows.Count; row++)
{
for (int col = 0; col < table.Columns.Count; col++)
{
DataCollection dtTable = new DataCollection()
{
rowNumber = row,
colName = table.Columns[col].ColumnName,
colValue = table.Rows[row - 1][col].ToString()
};
dataCol.Add(dtTable);
}
}
}
public string ReadData(int rowNumber, string columnName)
{
try
{
// Retriving data using LINQ to reduce much of iterations
string data = (from colData in dataCol
where colData.colName == columnName && colData.rowNumber == rowNumber
select colData.colValue).SingleOrDefault();
return data.ToString();
}
catch (Exception e)
{
return null;
}
}
internal class DataCollection
{
public int rowNumber { get; internal set; }
public string colName { get; internal set; }
public string colValue { get; internal set; }
}
}
}
and the TestClass:
[Test]
public void DataDrivenTest_FromExcel()
{
Driver = new ChromeDriver();
ExcelUtil util = new ExcelUtil();
util.PopulateInCollection(#"C:\dan\AutomationTest\TestData\test.xlsx");
Driver.FindElement(By.Id("contentPlaceholder_txtClientCode"))
.SendKeys(util.ReadData(i));
Driver.FindElement(By.XPath("//*[#id='btnLogin']")).Click();
Driver.FindElement(By.XPath("//*
[#id='tabContent0']/table/tbody/tr[2]/td[1]")).Click();
Driver.FindElement(By.Id("contentPlaceholder_txtcloseButton")).Click();
Driver.Quit
}
List<DataCollection> dataCol = new List<DataCollection>();
public void PopulateInCollection(string fileName, string sheetName)
{
DataTable table = ExcelToDataTable(fileName, sheetName);
//Iterate through the rows and columns of the Table
for (int row = 1; row <= table.Rows.Count; row++)
{
for (int col = 0; col <= table.Columns.Count; col++)
{
Datacollection dtTable = new Datacollection()
{
rowNumber = row,
colName = table.Columns[col].ColumnName,
colValue = table.Rows[row - 1][col].ToString()
};
//Add all the details for each row
dataCol.Add(dtTable);
}
}
}
public DataTable ExcelToDaTable(string fileName, string sheetName)
{
// open file and returns as stream
FileStream stream = File.Open(fileName, FileMode.Open, FileAccess.Read);
// create openXmlReader via ExcelReaderFactory
IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream);
//Set the first row as column name
var result = excelReader.AsDataSet(new ExcelDataSetConfiguration()
{
ConfigureDataTable = (_) => new ExcelDataTableConfiguration()
{
UseHeaderRow = true
}
});
// Return as dataset
DataSet result = excelReader.AsDataSet();
// Get all tables
DataTableCollection table = result.Tables;
// Store in Database
DataTable resultTable = table[sheetName];
return resultTable;
}
#End
//Define this first
util.PopulateInCollection("fileName", "sheetName");
//Reading from excel file
util.ReadData(rowNumber, columnName)
<?xml version="1.0" standalone="yes"?>
<Subject>
<Book>
<Name>ASP.NET</Name>
<Author>ABC</Author>
<Published>2018</Published>
<Price>$100</Price>
</Book>
</Subject>
The above is xml file i have . I want to Store those xml nodes and values in Dictionary and also i need to access the values by using corresponding nodes.
Then only it will works ..
What i have tried is:
XmlTextReader reader = new XmlTextReader("myxmlfile.xml");
Dictionary<string, string> dict = new Dictionary<string, string>();
string field = "";
string strlayer = "";
bool Name = false;
int count = 0;
while (reader.Read())
{
XmlNodeType nt = reader.NodeType;
switch (reader.NodeType)
{
case XmlNodeType.Element:
switch (reader.Name)
{
case "Subject":
count = 1;
break;
case "Book":
count = 1;
break;
case "Name":
if (count == 1)
{
strlayer = reader.Value;
MessageBox.Show(strlayer);
}
else
Name = true;
break;
}
break;
}
}
Am trying the code but its not working.Anyone's help is appreciable ....
i just want to store for that value to that Particular node That's it....
you can use this code:
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.Load("YOUR_PATH");
Dictionary<string, string> dict = new Dictionary<string, string>();
foreach (XmlElement item in xmlDocument.SelectSingleNode("Subject/Book"))
{
dict.Add(item.Name, item.InnerText);
}
if you have only one "Book" element this code help you. but if you have several Book item so you can not use a dictionary to save them.
Using Xml Linq :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq ;
namespace ConsoleApplication48
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
Dictionary<string, string> dict = doc.Descendants("Book").FirstOrDefault().Elements()
.GroupBy(x => x.Name.LocalName, y => (string)y)
.ToDictionary(x => x.Key, y => y.FirstOrDefault());
}
}
}
I am using CsvHelper lib to read CSV file and I can successfully read the file with the lib. However I cannot use SQL condition to filter values. How can I do that without using SQL Server. I am really stuck on it.
It was very easy with Pandas and Pandasql libs in Python but it is being too hard in C#..
My Code:
public static void Main(string[] args)
{
var fileInfo = new FileInfo(#"filePath");
using (TextReader reader = fileInfo.OpenText())
using (var csvReader = new CsvReader(reader))
{
csvReader.Configuration.Delimiter = ",";
csvReader.Configuration.HasHeaderRecord = false;
csvReader.Configuration.IgnoreQuotes = true;
csvReader.Configuration.TrimFields = true;
csvReader.Configuration.WillThrowOnMissingField = false;
while (csvReader.Read())
{
var myStrinVar = csvReader.GetField<string>(0);
Console.Write(myStrinVar); //SELECT * FROM table...
}
}
}
I would suggest using LINQ to filter your results.
https://msdn.microsoft.com/en-us/library/bb397906.aspx
Say you have some class MyClass that you can serialize the lines in your file into.
For example:
public class MyClass
{
public int ID { get; set; }
}
var records = csv.GetRecords<MyClass>().ToList();
var filtered = records.Where(r => r.ID >= 10);
That example is a bit contrived but you can use any boolean expression you like in the where clause.
I know this is too late for OP, but the issue with the accepted answer is that you have to read in the entire result set to memory which may not be tenable for large files. Also, if you can extend this code below to get the top N rows without having to read the entire CSV if you find matches early in the file.
public static void Main(string[] args)
{
var fileInfo = new FileInfo(#"filePath");
var where = ""; //Code to set up where clause part of query goes here
using (TextReader reader = fileInfo.OpenText())
using (var csvReader = new CsvReader(reader))
{
csvReader.Configuration.Delimiter = ",";
csvReader.Configuration.HasHeaderRecord = false;
csvReader.Configuration.IgnoreQuotes = true;
csvReader.Configuration.TrimFields = true;
csvReader.Configuration.WillThrowOnMissingField = false;
DataTable dt = null;
while (csvReader.Read())
{
//Use the first row to initialize the columns.
if (dt == null)
{
dt = new DataTable();
for (var i = 0; i < csvReader.FieldCount; i++)
{
var fieldType = csvReader.GetFieldType(i);
DataColumn dc;
if (fieldType.IsNullableType())
{
dc = new DataColumn(csvReader.GetName(i), Nullable.GetUnderlyingType(fieldType));
dc.AllowDBNull = true;
}
else
dc = new DataColumn(csvReader.GetName(i), data.GetFieldType(i));
dt.Columns.Add(dc);
}
}
//Map DataReader to DataRow
var newRow = dt.Rows.Add();
foreach(DataColumn col in dt.Columns)
{
newRow[col.ColumnName] = csvReader[col.ColumnName];
}
//Create a temporary DataView and filter it with the where clause.
DataView dv = new DataView(dt);
dv.RowFilter = where;
var data = dv.Count > 0 ? dv[0] : null;
if(data != null)
{
//Row in here matches your where clause.
//Code to read this row or do something with it.
}
//Empty the temporary data table.
dt.Rows.Clear();
}
}
}
Here is my code:
using (System.Net.WebResponse tmpRes = tmpReq.GetResponse())
{
using (System.IO.Stream tmpStream = tmpRes.GetResponseStream())
{
using (System.IO.TextReader tmpReader = new System.IO.StreamReader(tmpStream))
{
string fileContents = tmpReader.ReadToEnd();
for (int i = 0; i < fileContents.Length; i++)
{
if (fileContents[i] == "")
{
fileContents[i] = "null";
}
}
using (Stream s = GenerateStreamFromString(fileContents))
{}
}
}
}
this shows error 'string' to 'char' convert implicitly. Is there any other way to set "NULL" in empty fields in CSVReader
You are not using the CsvReader at all. You are also not splitting the string by your delimiter to get "cells". However, you can load a DataTable from the CsvReader and modify that.
Here's an example presuming tab as delimiter:
var tblCSV = new DataTable();
using (System.Net.WebResponse tmpRes = tmpReq.GetResponse())
using (System.IO.Stream tmpStream = tmpRes.GetResponseStream())
using (System.IO.TextReader tmpReader = new System.IO.StreamReader(tmpStream))
using (var csv = new CsvReader(tmpReader, true, '\t', '"', '\0', '\0', ValueTrimmingOptions.All))
{
csv.MissingFieldAction = MissingFieldAction.ParseError;
csv.DefaultParseErrorAction = ParseErrorAction.RaiseEvent;
csv.ParseError += csv_ParseError;
csv.SkipEmptyLines = true;
// load into DataTable
tblCSV.Load(csv, LoadOption.OverwriteChanges, csvTable_FillError);
}
Now loop the rows and columns and modify them accordingly:
foreach(DataRow row in tblCSV.Rows)
{
foreach(DataColumn col in tblCSV.Columns)
{
if(string.IsNullOrWhiteSpace(row.Field<string>(col)))
row.SetField(col, "null");
}
}
Update related to your comment:
I wants to add NULL value in empty cells in sql database when the csv
data Save in database. Is there any other way?
You could simply use the loop above to update your table instead:
using (var con = new SqlConnection("ConnectionString"))
{
con.Open();
foreach (DataRow row in tblCSV.Rows)
{
using (var cmd = new SqlCommand("INSERT INTO table(Col1,Col2) VALUES (#Col1,Col2);", con))
{
string col1 = row.Field<string>("Col1");
if (string.IsNullOrWhiteSpace(col1))
col1 = null;
string col2 = row.Field<string>("Col2");
if (string.IsNullOrWhiteSpace(col2))
col2 = null;
cmd.Parameters.AddWithValue("#col1", col1);
cmd.Parameters.AddWithValue("#col2", col2);
int inserted = cmd.ExecuteNonQuery();
}
}
}