I am trying to parse an XML file into a datatable that I can furhter load into a SQL server database. My first step is to parse the XML.
This is the sample file:
<Report>
<Summary>
<Member Name="Krispy Kreme Doughnuts Inc" ID="7003200" />
<BatchFile Name="ftpoobt200303130547" SendingClientName="" ID="000000587" Format="ANSI" Date="2020-03-03 13:06:31" Result="Successful" Creator="STP-KRISPYKREMED" />
<Total NoTransactions="3" /><Success NoTransactions="3" /><Fail NoTransactions="0" /></Summary>
<Transactions><Transaction RequestID="2593" TransactionID="7003534217" Status="Accepted" Date="2020-03-03 13:06:31" DueDate="2021-01-25 00:00:00" Currency="USD" PaymentAmount="25,584.79" SourceAccount="6190000020" SupplierName="JTM Foods LLC" SupplierAccount="6190000080" MessageText="$$" MessageDescription="" />
<Transaction RequestID="2594" TransactionID="7003534218" Status="Accepted" Date="2020-03-03 13:06:31" DueDate="2021-02-25 00:00:00" Currency="USD" PaymentAmount="327,538.77" SourceAccount="6190000020" SupplierName="BakeMark USA" SupplierAccount="6190000060" MessageText="$$" MessageDescription="" />
<Transaction RequestID="2595" TransactionID="7003534219" Status="Accepted" Date="2020-03-03 13:06:31" DueDate="2021-02-25 00:00:00" Currency="USD" PaymentAmount="48,588.70" SourceAccount="6190000020" SupplierName="Bay State Milling Company" SupplierAccount="6190000070" MessageText="$$" MessageDescription="" />
</Transactions></Report>
And this is my current code:
private static DataTable RetrieveXML(string fileToLoad, string source)
{
DataTable dt = new DataTable();
XmlDocument doc= new XmlDocument();
doc.Load(fileToLoad);
if(doc.ChildNodes[0]!=null)
dt.Columns.Add(doc.ChildNodes[0].Name); //Assuming you want the rood node to be the only column of the datatable
//iterate through all the childnodes of your root i.e. Category
foreach(XmlNode node in doc.ChildNodes[0].ChildNodes )
{
dt.Rows.Add(node.Name);
}
return dt;
}
I can find the first and second outer nodes (summary and transaction), but not sure how to get down to the actual data. For example I need the name and value, id and value from the member node. Those are the actual fields in the database.
Try using Xml Linq :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Data;
using System.Globalization;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
DataTable dt = new DataTable();
dt.Columns.Add("RequestID", typeof(int));
dt.Columns.Add("TransactionID", typeof(string));
dt.Columns.Add("Status", typeof(string));
dt.Columns.Add("Date", typeof(DateTime));
dt.Columns.Add("DueDate", typeof(DateTime));
dt.Columns.Add("Currency", typeof(string));
dt.Columns.Add("PaymentAmount", typeof(decimal));
dt.Columns.Add("SourceAccount", typeof(string));
dt.Columns.Add("SupplierName", typeof(string));
dt.Columns.Add("SupplierAccount", typeof(string));
dt.Columns.Add("MessageText", typeof(string));
dt.Columns.Add("MessageDescription", typeof(string));
XDocument doc = XDocument.Load(FILENAME);
Dictionary<string, Dictionary<string, string>> summary = doc.Descendants("Summary").Elements()
.GroupBy(x => x.Name.LocalName, y => y.Attributes()
.GroupBy(a => a.Name.LocalName, b => (string)b)
.ToDictionary(a => a.Key, b => b.FirstOrDefault()))
.ToDictionary(x => x.Key, y => y.FirstOrDefault());
foreach (XElement transaction in doc.Descendants("Transaction"))
{
dt.Rows.Add(new object[] {
(int)transaction.Attribute("RequestID"),
(string)transaction.Attribute("TransactionID"),
(string)transaction.Attribute("Status"),
DateTime.ParseExact((string)transaction.Attribute("Date"), "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture),
DateTime.ParseExact((string)transaction.Attribute("DueDate"), "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture),
(string)transaction.Attribute("Currency"),
decimal.Parse((string)transaction.Attribute("PaymentAmount")),
(string)transaction.Attribute("SourceAccount"),
(string)transaction.Attribute("SupplierName"),
(string)transaction.Attribute("SupplierAccount"),
(string)transaction.Attribute("MessageText"),
(string)transaction.Attribute("MessageDescription")
});
}
}
}
}
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) });
}
}
}
}
Its been awhile I have been programming in c# and have a question about creating a data table in a class and then trying to access that datatable from another class or mvc controller. Some advice and some explanation would be much appreciated
Current class
using OfficeOpenXml;
using System;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using ppms_excel.Models;
namespace ppms_excel.Models
{
public class PODataTable
{
public DataTable LDataTable
{
get
{
DataTable legalEntityTable = new DataTable("legal_entitiy");
legalEntityTable.Columns.Add("Id", typeof(int));
legalEntityTable.Columns.Add("ExternalId", typeof(string));
legalEntityTable.Columns.Add("Source", typeof(string));
legalEntityTable.Columns.Add("XpressEntityId", typeof(int));
legalEntityTable.Columns.Add("EntityTypeId", typeof(int));
legalEntityTable.Columns.Add("EntityName", typeof(string));
legalEntityTable.Columns.Add("EIN", typeof(string));
legalEntityTable.Columns.Add("Descripton", typeof(string));
legalEntityTable.Columns.Add("Address1", typeof(string));
legalEntityTable.Columns.Add("Address2", typeof(string));
legalEntityTable.Columns.Add("City", typeof(string));
legalEntityTable.Columns.Add("State", typeof(string));
legalEntityTable.Columns.Add("PostalCode", typeof(string));
legalEntityTable.Columns.Add("WebSiteUrl", typeof(string));
legalEntityTable.Columns.Add("PricingAgreementTime", typeof(DateTimeOffset));
legalEntityTable.Columns.Add("AgreementTime", typeof(DateTimeOffset));
legalEntityTable.Columns.Add("AgreementSoourceIP", typeof(string));
legalEntityTable.Columns.Add("CustomerServiceEmail", typeof(string));
legalEntityTable.Columns.Add("CustomerServicePhoneNumber", typeof(string));
legalEntityTable.Columns.Add("Active", typeof(bool));
legalEntityTable.Columns.Add("TimeZone", typeof(string));
legalEntityTable.Columns.Add("CreateTime", typeof(DateTimeOffset));
legalEntityTable.Columns.Add("RiskToken", typeof(string));
legalEntityTable.Columns.Add("DBA", typeof(string));
legalEntityTable.Columns.Add("YearOfFormation", typeof(string));
legalEntityTable.Columns.Add("DateOfFormation", typeof(string));
return legalEntityTable;
}
}
}
}
Controller
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using OfficeOpenXml;
using ppms_excel.Models;
using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using System.IO;
using Excel = Microsoft.Office.Interop.Excel;
namespace ppms_excel.Controllers
{
public class LoadDataTableController1 : Controller
{
public IActionResult Index()
{
//var x=new PODataTable().LDataTable.TableName;
ExcelPackage ld = new ExcelPackage();
ExcelWorksheet worksheet = ld.Workbook.Worksheets.FirstOrDefault();
if (worksheet == null)
{
//return or alert message here
}
else
{
var colcount= worksheet.Dimension.Columns;
string[] coltitle = new string[colcount];
for (int i = 1; i <= colcount; i++)
{
coltitle[i - 1] = (string) worksheet.Cells[1, i].Value;
}
//read excel file data and add data in model.StaffInfoViewModel.StaffList
var rowCount = worksheet.Dimension.Rows;
var colCount = worksheet.Dimension.Columns;
**PODataTable Le = new PODataTable().LDataTable;**
}
return View();
}
}
}
is this the correct way to get the datatable instantiated in the controller?
PODataTable Le = new PODataTable().LDataTable;
thanks
Sure, there are many ways to solve this. In general, it's always a good idea to separate controller logic from model or utility logic, like you have done. The reference to ppms_excel.Models will allow you to use that class just like you have it.
In general, I would be careful about using properties for building and passing back more complicated objects. This can lead to poor performance since the object will be recreated each time. If possible, store the built object in a local variable of the utility class and return that instead. This will prevent unnecessary recreates (if it will be the same each time).
I'm new to C#. I know that datatable is very efficient for reading an entire SQL table and outputting data to griddataview. However I need to do some parsing before storing the data in my griddataview. I was thinking reading the table row by row and grouping the data when applicable. Would a datatable or a list be more applicable in my case?
ORIGINAL TABLE PARSED TABLE I need to pass to datagridview
Name Workdate Name M T W TH F SAT SUN
Nicole WED Nicole Y Y Y
Nicole THR Jason Y
Nicole MON
Jason Tue
Try following :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Dictionary<string, string> dict = new Dictionary<string, string>() {
{"MON", "M"},{"TUE", "T"},{"WED", "W"},{"THR", "TH"},{"FRI", "F"},{"SAT", "SAT"},{"SUN", "SUN"}};
DataTable dt = new DataTable();
dt.Columns.Add("Name", typeof(string));
dt.Columns.Add("Workdate", typeof(string));
dt.Rows.Add(new object[] { "Nicole", "WED" });
dt.Rows.Add(new object[] { "Nicole", "THR" });
dt.Rows.Add(new object[] { "Nicole", "MON" });
dt.Rows.Add(new object[] { "Jason", "TUE" });
DataTable pivot = new DataTable();
pivot.Columns.Add("Name",typeof(string));
DataColumn[] columns = dict.Select(x => new DataColumn(x.Value, typeof(string))).ToArray();
pivot.Columns.AddRange(columns);
var people = dt.AsEnumerable().GroupBy(x => x.Field<string>("Name")).ToArray();
foreach (var person in people)
{
DataRow pivotRow = pivot.Rows.Add();
pivotRow["Name"] = person.Key;
foreach (DataRow row in person)
{
string day = row.Field<string>("Workdate");
pivotRow[dict[day]] = "Y";
}
}
}
}
}
I have to serialize a class to achieve below format. Values that
appear in 'repeatnode' are fetched from DB. Could anyone help me
form a class serialize in to below xml. Also how the values can be
assigned to the repeating tags.
<ParentNode>
<docInfo>
<doc>name</doc>
<fileInfo>
<Date>2016-02-25T12:52:00</Date>
<software>Export</software>
<Creator>export</Creator>
</fileInfo>
</docInfo>
<repeatnode id="XXXXXXXXXXX" idval="XXXXXXXX" idsub="XXXX">
<name>XXXX</name>
<namebore>namebore</namebore>
</repeatnode>
<repeatnode id="XXXXXXXXXXX" idval="XXXXXXXX" idsub="XXXX">
<name>XXXX</name>
<namebore>namebore</namebore>
</repeatnode>
<repeatnode id="XXXXXXXXXXX" idval="XXXXXXXX" idsub="XXXX">
<name>XXXX</name>
<namebore>namebore</namebore>
</repeatnode>
</ParentNode>
Use a join query to the database to get the datatable below. Then use the code below to create the xml
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Linq;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
DataTable dt = new DataTable();
dt.Columns.Add("DocName", typeof(string));
dt.Columns.Add("Date", typeof(DateTime));
dt.Columns.Add("software", typeof(string));
dt.Columns.Add("Creator", typeof(string));
dt.Columns.Add("nodeId", typeof(string));
dt.Columns.Add("idVal", typeof(string));
dt.Columns.Add("idSub", typeof(string));
dt.Columns.Add("nodeName", typeof(string));
dt.Columns.Add("namebore", typeof(string));
dt.Rows.Add(new object[] { "name", DateTime.Parse("2016-02-25T12:52:00"), "Export", "export", "XXXXXXXXXXX", "XXXXXXXX", "XXXX", "XXXX", "namebore" });
dt.Rows.Add(new object[] { "name", DateTime.Parse("2016-02-25T12:52:00"), "Export", "export", "XXXXXXXXXXX", "XXXXXXXX", "XXXX", "XXXX", "namebore" });
dt.Rows.Add(new object[] { "name", DateTime.Parse("2016-02-25T12:52:00"), "Export", "export", "XXXXXXXXXXX", "XXXXXXXX", "XXXX", "XXXX", "namebore" });
dataGridView1.DataSource = dt;
var groups = dt.AsEnumerable()
.GroupBy(x => new { doc = x.Field<string>("DocName"), date = x.Field<DateTime>("date"), software = x.Field<string>("software"), creator = x.Field<string>("Creator") }).ToList();
XElement parentNode = new XElement("ParentNode");
foreach (var group in groups)
{
XElement docInfo = new XElement("docInfo", new object[] {
new XElement("doc", group.Key.doc),
new XElement("fileinfo", new object[] {
new XElement("Date", group.Key.date.ToString("yyyy-MM-ddThh:mm:ss")),
new XElement("softwate", group.Key.software),
new XElement("Creator", group.Key.creator)
})
});
parentNode.Add(docInfo);
foreach (var row in group)
{
XElement repeatnode = new XElement("repeatnode", new object[] {
new XAttribute("id", row.Field<string>("nodeId")),
new XAttribute("idval", row.Field<string>("idVal")),
new XAttribute("idsub", row.Field<string>("idSub")),
new XElement("name", row.Field<string>("nodeName")),
new XElement("namebore", row.Field<string>("namebore"))
});
parentNode.Add(repeatnode);
}
}
}
}
}
I know there are lots of resources that show how to bind dataGridViews to XML files or populate from XML, but the XML i'm using as source is a bit more complex than any example I've seen used and I'm struggling. (although it really shouldn't be difficult)
I basically need to run several queries (I think) to get the data I want to populate the DGV, because the elements I want the content from are on different parent nodes of the XML.
Here is what I have, and the comments should show you what I'm trying to achieve:
XDocument xmlDoc = XDocument.Load("Techdocx_dml.xml");
var q = from c in xmlDoc.Root.Descendants("dmentry")
.Descendants("avee")
//.Descendants("dmtitle") I also need to access this descendant
select new
{
modelic = c.Element("modelic").Value,
sdc = c.Element("sdc").Value,
chapnum = c.Element("chapnum").Value,
section = c.Element("section").Value,
subsect = c.Element("subsect").Value,
subject = c.Element("subject").Value,
discode = c.Element("discode").Value,
discodev = c.Element("discodev").Value,
incode = c.Element("incode").Value,
incodev = c.Element("incodev").Value,
itemloc = c.Element("itemloc").Value,
// techname = c.Element("techname").Value,
//need this value, which is on the "dmtitle" node, not the "avee" node
};
dataGridView1.DataSource = q.ToList();
dataGridView1.ColumnHeadersVisible = false;
dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
This is what i want in my dataGridView:
AA A 32 3 5 00 01 A 018 A A | Some title 1 | Introduction
AA A 32 3 5 00 01 A 920 A A | Some title 2 | Some infoname 2
How do I achieve this please? Example XML below:
<dml xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<dmentry>
<addresdm>
<dmc>
<avee>
<modelic>AA</modelic>
<sdc>A</sdc>
<chapnum>32</chapnum>
<section>3</section>
<subsect>5</subsect>
<subject>00</subject>
<discode>01</discode>
<discodev>A</discodev>
<incode>018</incode>
<incodev>A</incodev>
<itemloc>A</itemloc>
</avee>
</dmc>
<dmtitle>
<techname>Some title 1</techname>
<infoname>Introduction</infoname>
</dmtitle>
<issno issno="001" type="New"/>
<issdate year="2016" month="06" day="10"/>
<language language="SX" country="GB"/>
</addresdm>
<security class="1"/>
</dmentry>
<dmentry>
<addresdm>
<dmc>
<avee>
<modelic>AA</modelic>
<sdc>A</sdc>
<chapnum>32</chapnum>
<section>3</section>
<subsect>5</subsect>
<subject>00</subject>
<discode>01</discode>
<discodev>A</discodev>
<incode>920</incode>
<incodev>A</incodev>
<itemloc>A</itemloc>
</avee>
</dmc>
<dmtitle>
<techname>Some title 2</techname>
<infoname>Some infoname 2</infoname>
</dmtitle>
<issno issno="001" type="New"/>
<issdate year="2016" month="06" day="10"/>
<language language="SX" country="GB"/>
</addresdm>
<security class="1"/>
</dmentry>
</dml>
Try this :
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Linq;
namespace WindowsFormsApplication11
{
public partial class Form1 : Form
{
const string FILENAME = #"c:\temp\test.xml";
public Form1()
{
InitializeComponent();
DataTable dt = new DataTable();
dt.Columns.Add("modelic", typeof(string));
dt.Columns.Add("sdc", typeof(string));
dt.Columns.Add("chapnum", typeof(string));
dt.Columns.Add("section", typeof(string));
dt.Columns.Add("subsect", typeof(string));
dt.Columns.Add("subject", typeof(string));
dt.Columns.Add("discode", typeof(string));
dt.Columns.Add("discodev", typeof(string));
dt.Columns.Add("incode", typeof(string));
dt.Columns.Add("incodev", typeof(string));
dt.Columns.Add("itemloc", typeof(string));
dt.Columns.Add("techname", typeof(string));
dt.Columns.Add("infoname", typeof(string));
XDocument doc = XDocument.Load(FILENAME);
foreach (XElement addresdm in doc.Descendants().Where(x => x.Name.LocalName == "addresdm"))
{
XElement avee = addresdm.Descendants("avee").FirstOrDefault();
XElement dmtitle = addresdm.Descendants("dmtitle").FirstOrDefault();
dt.Rows.Add(new object[] {
(string)avee.Element("modelic"),
(string)avee.Element("sdc"),
(string)avee.Element("chapnum"),
(string)avee.Element("section"),
(string)avee.Element("subsect"),
(string)avee.Element("subject"),
(string)avee.Element("discode"),
(string)avee.Element("discodev"),
(string)avee.Element("incode"),
(string)avee.Element("incodev"),
(string)avee.Element("itemloc"),
(string)dmtitle.Element("techname"),
(string)dmtitle.Element("infoname")
});
}
dataGridView1.DataSource = dt;
}
}
}