tags:

views:

121

answers:

1

I am currently working with a webservice to pull a report about users in a remote support system.

After pulling my report and receiving the result, I am given the following string back by the method:

<report><header><field id="0">Source</field><field id="1">Session ID</field><field id="2">Date</field><field id="3">Name</field><field id="24">Technician Name</field><field id="25">Technician ID</field></header><data><row><field id="0">Email</field><field id="1">55037806</field><field id="2">4/13/2010 2:28:06 AM</field><field id="3">Bill Gates</field><field id="24">John</field><field id="25">1821852</field></row><row><field id="0">Telephone</field><field id="1">55034548</field><field id="2">4/13/2010 12:59:44 AM</field><field id="3">Steve Jobs</field><field id="24">John</field><field id="25">1821852</field></row></data></report>

After receiving this string, I need to take it and display the actual data in a datagridview. I've tried putting it into an XMLDocument then reading that, but it seems to keep failing. Just interested in another set of eyes :) Application is written in C# in VS2010.

+1  A: 

You could use Linq to XML to build a DataTable with the column names from the XML file, then set that table as the DataSource of the DataGridView :

        string xml = theWebService.TheMethod();
        XDocument doc = XDocument.Parse(xml);
        var queryHeaders =
            from field in doc.Root.Element("header").Elements("field")
            select new
            {
                Id = field.Attribute("id").Value,
                Name = field.Value
            };

        var headers = queryHeaders.ToDictionary(f => f.Id, f => f.Name);

        DataTable table = new DataTable();
        foreach (var kvp in headers)
        {
            table.Columns.Add(kvp.Value);
        }

        Func<XElement, DataRow> rowGenerator =
            element =>
            {
                var row = table.NewRow();
                foreach (var field in element.Elements("field"))
                {
                    string fieldId = field.Attribute("id").Value;
                    string columnName = headers[fieldId];
                    string value = field.Value;
                    row[columnName] = value;
                }
                return row;
            };

        var rows =
            from rowElement in doc.Root.Element("data").Elements("row")
            select rowGenerator(rowElement);

        foreach (var row in rows)
        {
            table.Rows.Add(row);
        }

        dataGridView.AutoGenerateColumns = true;
        dataGridView.DataSource = table;

Note that the code above only works if all fields have distinct names. If that's not the case, you might want to use the field ID as the DataColumn name, and change the headers of the DGV with the actual field names

Thomas Levesque
Worked like a charm, I appreciate the guidance!
Justin Daniels
Actually, pulling longer reports yields multiple "header" entries in the XML. Any thoughts on that anyone? Thomas' suggestion works great when there's only one header being sent back.
Justin Daniels
Important to note that the <header></header> string is identical in each additional case in the XML, so maybe just parse out duplicate header entries in the string?
Justin Daniels
You can use `doc.Root.Elements("header").First()` to keep only the first `<header>` element
Thomas Levesque
Working perfect now, thanks!
Justin Daniels