Juan Le Roux
Juan Le Roux

Reputation: 89

Populate Datagrid From xml file

I've looked at many answers on this topic but was unable to find the answer to my question, so apologies in advance if I missed this answer somewhere else.

I would like to add attributes of a particular object id to a datagrid. The routine that I have developed unfortunately adds all attributes to the datagrid and not just the attributes of the selected object.

I have the following xml file structure:

<?xml version="1.0" encoding="UTF-8"?>
<project>
  <configuration>
    <general>
      <verbose>True</verbose>
    </general>
    <architecture>
      <site reference="Demo Site Reference" type="WTP" id="0001" />
      <rtu dnp="77" ip="10.10.10.77" type="Schneider Electric SCADAPack 442" />
      <radio ip="10.10.10.76" />
      <hmi ip="10.10.10.75" />
    </architecture>
  </configuration>
  <database>
    <object id="0" name="object 0" description="Entry Description 0" date="22.06.2018 00:00:00" archestra="Export">
      <attributes>
        <attribute id="0" name="Attribute 0" description="Attribute 0 Description" note="Attribute 0 Note" />
        <attribute id="1" name="Attribute 1" description="Attribute 1 Description" note="Attribute 1 Note" />
      </attributes>
    </object>
    <object id="1" name="object 1" description="Entry Description 1" date="22.06.2018 00:00:00" archestra="Export">
      <attributes>
        <attribute id="0" name="Attribute 0" description="Attribute 0 Description" note="Attribute 0 Note" />
        <attribute id="1" name="Attribute 1" description="Attribute 1 Description" note="Attribute 1 Note" />
        <attribute id="2" name="Attribute 2" description="Attribute 2 Description" note="Attribute 2 Note" />
        <attribute id="3" name="Attribute 3" description="Attribute 3 Description" note="Attribute 3 Note" />
      </attributes>
    </object>
    <object id="2" name="object 2" description="Entry Description 2" date="22.06.2018 00:00:00" archestra="Export">
      <attributes>
        <attribute id="0" name="Attribute 0" description="Attribute 0 Description" note="Attribute 0 Note" />
        <attribute id="1" name="Attribute 1" description="Attribute 1 Description" note="Attribute 1 Note" />
        <attribute id="2" name="Attribute 2" description="Attribute 2 Description" note="Attribute 2 Note" />
      </attributes>
    </object>
  </database>
</project>

The following routine adds all attributes:

    public static DataTable PopulateGrid(string file, string id)
    {
        //DataTable that will hold the found results
        DataTable results = new DataTable("SearchResults");
        //DataRow (used later)
        DataRow row = null;

        results.Columns.Add("id", typeof(string));
        results.Columns.Add("name", typeof(string));
        results.Columns.Add("description", typeof(string));

        XmlDocument xmldocument = new XmlDocument();
        xmldocument.Load(file);

        //** Change This **
        string query = "/project/database/object";
        string query2 = "/project/database/object/attributes/attribute";

        //now we loop through the list
        foreach (XmlNode xmlnode in xmldocument.SelectNodes(query))
        {
            if (xmlnode.Attributes["id"].Value == id)
            {
                foreach (XmlNode xmlnode2 in xmldocument.SelectNodes(query2))
                {
                    row = results.NewRow();

                    row[0] = xmlnode2.Attributes["id"].Value;
                    row[1] = xmlnode2.Attributes["name"].Value;
                    row[2] = xmlnode2.Attributes["description"].Value;

                    results.Rows.Add(row);
                }
            }
        }

        //now return the DataTable
        return results;
    }

Any help to solve this would be greatly appreciated.

Kind Regards

Upvotes: 0

Views: 113

Answers (3)

Alexander Petrov
Alexander Petrov

Reputation: 14251

You have to get the attributes from the already found node, not from the entire document.

string query2 = "./attributes/attribute"; // path from current node


// use xmlnode instead of xmldocument
foreach (XmlNode xmlnode2 in xmlnode.SelectNodes(query2))

Upvotes: 2

croth
croth

Reputation: 21

In your second for loop, you call

xmldocument.SelectNodes(query2)

which selects all the nodes from the document which match query2.

your could change your code to:

        string query = "/project/database/object['" + id + "']";
        string query2 = "attributes/attribute";

        var obj = xmldocument.SelectSingleNode(query);

        foreach (XmlNode xmlnode2 in obj.SelectNodes(query2))
        {
            row = results.NewRow();

            row[0] = xmlnode2.Attributes["id"].Value;
            row[1] = xmlnode2.Attributes["name"].Value;
            row[2] = xmlnode2.Attributes["description"].Value;

            results.Rows.Add(row);
        }

Upvotes: 1

Cetin Basoz
Cetin Basoz

Reputation: 23837

I think it would be much easier if you have used Linq To XML. ie:

public static IEnumerable<MyData> PopulateGrid(string file, string id)
{
    var xml = XElement.Load(file);
    var result = xml.Element("database").Elements("object")
    .SelectMany(o => o.Element("attributes").Elements("attribute"))
    .Where(x => (string)x.Attribute("id") == id)
    .Select(a => new MyData
    {
        Id = (string)a.Attribute("id"),
        Name = (string)a.Attribute("name"),
        Description = (string)a.Attribute("description")
    });

    return result;
}

public class MyData
{
    public string Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
}

Upvotes: 1

Related Questions