0

This is the XML file I'm trying to fill the DataGridView with:

<?xml version="1.0" encoding="utf-8"?>
<Transactions>
<Transaction>
    <Name>David</Name>
    <Amount>123</Amount>
    <Date>11/11/2011</Date>
</Transaction>
<Transaction>
    <Name>Mark</Name>
    <Amount>400</Amount>
    <Date>12/12/2012</Date>
</Transaction>
<Transaction
    ><Name>Norah</Name>
    <Amount>400</Amount>
    <Date>12/12/2012</Date>
</Transaction>
<Transaction>
    <Name>Cecil</Name>
    <Amount>400</Amount>
    <Date>12/12/2012</Date>
</Transaction>

</Transactions>

This is the last code I tried, but it did not work.
Its C# asp.Net ( input array is more than number of columns I only have 3 columns (Name, Amount and Date)

DataTable dt = new DataTable();
XDocument doc = XDocument.Load(filepath);
foreach (XElement transactions in doc.Descendants().Where(x => x.Name.LocalName == "Transactions")){
    XElement Name = transactions.Descendants("Name").FirstOrDefault();
    XElement Amount = transactions.Descendants("Amount").FirstOrDefault();
    XElement date = transactions.Descendants("Date").FirstOrDefault();                
    dt.Rows.Add(new object[]
    {
        (string)Name.Element("Name"),
        (string)Amount.Element("Amount"),
        (string)date.Element("Date")
    });
}
dataGridView1.DataSource = dt;
4
  • xml linq is case sensitive and you need a capital 't' : "transactions" Commented Dec 9, 2018 at 0:54
  • @jdweng check it now Commented Dec 9, 2018 at 0:59
  • The DataTable ... dt... has no columns. Commented Dec 9, 2018 at 2:24
  • What is DataGridView? Are you mean GridView? Are you using WebForms? Maybe you are confused with WinForms? Commented Dec 9, 2018 at 3:35

2 Answers 2

1

There are a few problems with the posted code.

First, the “newly” created DataTable dt … is never given any columns. Therefore, it is not surprising to see the line of code… dt.Rows.Add(… crash and burn. Hence the current error. Adding the three lines of code below should solve this missing column error.

dt.Columns.Add("Name", typeof(string));
dt.Columns.Add("Amount", typeof(string));
dt.Columns.Add("Date", typeof(string));

Unfortunately fixing this issue will only reveal another problem…

The foreach loop is grabbing the XML “elements” improperly. I am guessing there is an easier way to do this however, using the posted XML file and taking a closer look at the foreach loop code below…

foreach (XElement transactions in doc.Descendants().Where(x => x.Name.LocalName == "Transactions")) { … }

I am guessing you want to change the string "Transactions" to "Transaction" without the “s.” Leaving the “s” in the string is going to pick up the “whole” XML file since "Transactions" is the root. Therefore, the code will need further clarification as “which” “Name, Amount or Date” to use since there is more than one (1). In addition, the loop will only execute “once” since it is grabbing the root node. I recommend changing the value to "Transaction" to get what you are looking for.

Lastly, the code appears to be overly complicating things when grabbing the XElement value. As discussed above, we now know that we need to change the looping XElement variable to “Transaction,” this will mean that each “element” we get in the loop will look like…

<Transaction>
    <Name>David</Name>
    <Amount>123</Amount>
    <Date>11/11/2011</Date>
</Transaction>

Therefore… if we have an XElement called transaction like above, then a simple assignment…

string Name = Transaction.Element("Name").Value

should return the value we are looking for. It appears unnecessary to create the extra XElement variables (Name, Amount and date). The needed XElement already exist and it is called “transaction.” Given this, the code below should work as expected.

foreach (XElement transaction in doc.Descendants().Where(x => x.Name.LocalName == "Transaction")) {
      dt.Rows.Add(transaction.Element("Name").Value, transaction.Element("Amount").Value, transaction.Element("Date").Value);
    }

With that said, the code below demonstrates what is described above.

try {
    DataTable dt = new DataTable();
    dt.Columns.Add("Name", typeof(string));
    dt.Columns.Add("Amount", typeof(string));
    dt.Columns.Add("Date", typeof(string));
    XDocument doc = XDocument.Load(filepath);
    foreach (XElement transaction in doc.Descendants().Where(x => x.Name.LocalName == "Transaction")) {
      dt.Rows.Add(transaction.Element("Name").Value, transaction.Element("Amount").Value, transaction.Element("Date").Value);
    }
    dataGridView1.DataSource = dt;
}
catch (Exception ex) {
  MessageBox.Show("Error: " + ex.Message);
}

It should also be noted that when the code uses the line below…

transaction.Element("NodeName").Value

If “NodeName” does not exist, there is NO exception thrown, it will simply return null. Therefore, if you see the correct number of rows but missing data, it would be wise to check what is returned when reading from the XElement. Hope that helps.

Sign up to request clarification or add additional context in comments.

Comments

0

Try this code

  using System.Xml;

    XmlReader xmlFile = XmlReader.Create(@"C:\Users\Shubham\Documents\Visual Studio 2012\Projects\WindowsFormsApplication1\WindowsFormsApplication1\XMLFile1.xml", new XmlReaderSettings());
            DataSet dataSet = new DataSet();
            //Read xml to dataset
            dataSet.ReadXml(xmlFile);
            //Pass Transaction table to datagridview datasource
            dataGridView1.DataSource = dataSet.Tables["Transaction"];

            //Close xml reader

            xmlFile.Close();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.