How read use an ADO.NET DataSet to read XML files designed with nested attributes?

I am working on a project that is XML driven and I am using ADO.NET DataSet functionality to make reading the XML easier. However, I ran into a problem that really just a lack of knowledge on my part.

Problem
So I have DataSet created using an XML. The XML is using Nested attributes. And I just need to know how to loop properly through the DataSet Tables and their columns.

I have the following XML.

<?xml version="1.0" encoding="utf-8" ?>
<plugin PluginName="TestName" GroupName="Operating System Settings" Type="Single">
  <title>Plugin 1</title>
  <startTime>1:57:47 PM 2/16/2010</startTime>
  <endTime>1:58:03 PM 2/16/2010</endTime>
  <description>Runs the TestName process to determine something.</description>
  <section SectionName="Section1">
    <field FieldName="Field Name">
      <value Operand="EQ">Some Correct Setting1</value>
      <actionPlugin Name="" Type="Link" URL="">
        <executable>SomeAction1.exe</executable>
        <parameters>Param1 Param2</parameters>
      </actionPlugin>
    </field>
    <field FieldName="Field2">
      <value Operand="RG">900</value>
      <warningLevel>10%</warningLevel>
      <errorLevel>20%</errorLevel>
      <actionPlugin Name="ActionPlugin1" Type="Link" URL="http://www.somesite.tld/some/path/file.htm" />
    </field>
  </section>
  <section SectionName="Section2">
    <field FieldName="Field1">
      <value Operand="EQ">Some Correct Setting2</value>
      <actionPlugin Name="" Type="Link" URL="">
        <executable>SomeAction2.exe</executable>
        <parameters>Param1 Param2</parameters>
      </actionPlugin>
    </field>
    <field FieldName="Field2">
      <value Operand="RG">900</value>
      <warningLevel>10%</warningLevel>
      <errorLevel>20%</errorLevel>
      <actionPlugin Name="ActionPlugin1" Type="Link" URL="http://www.somesite.tld/some/path/file.htm" />
    </field>
  </section>
  <section SectionName="Section3">
    <field FieldName="Field1">
      <value Operand="EQ">Some Correct Setting3</value>
      <actionPlugin Name="" Type="Link" URL="">
        <executable>SomeAction3ds.exe</executable>
        <parameters>Param1 Param2</parameters>
      </actionPlugin>
    </field>
    <field FieldName="Field2">
      <value Operand="RG">900</value>
      <warningLevel>10%</warningLevel>
      <errorLevel>20%</errorLevel>
      <actionPlugin Name="ActionPlugin1" Type="Link" URL="http://www.somesite.tld/some/path/file.htm" />
    </field>
  </section>
</plugin>

So the DataSet is created with these tables (this is copied from the debugger):

– List Count = 5 System.Collections.ArrayList
+ [0] {Plugin} object {System.Data.DataTable}
+ [1] {Section} object {System.Data.DataTable}
+ [2] {Field} object {System.Data.DataTable}
+ [3] {Value} object {System.Data.DataTable}
+ [4] {ActionPlugin} object {System.Data.DataTable}

Table [1] {Section} has 3 rows.
Table [2] {Field} has 6 rows.

So the data looks like this:

Sections Table
Row 1
Row 2
Row 3

Fields Table
Row 1
Row 2
Row 3
Row 4
Row 5
Row 6

But I need to read it as follows:

Sections Table
Row 1  
Fields Table
Row 1
Row 2
Row 2  
Fields Table
Row 3
Row 4
Row 3  
Fields Table
Row 5
Row 6

So I had the code below, but for each Section Row it would loop through all six field rows, which is not what I intend.

string mFullPathToXML = "C:\My.xml";
DataSet ds;
ds.ReadXml(mFullPathToXML);

foreach (DataRow SectionRow in ds.Tables["Section"].Rows)
{
    foreach(DataRow FieldRow in ds.Tables["Field"].Rows)
    {
        // Looping through all rows, not just those that pertain to the section.
        // How to get only the two rows that belong to each Section row here?
    }
}

Solution
Well, I set out on a journey to figure this out. In a few search engines I use search phrases like:
DataSet XML Nested
DataSet XML Nested Relation
DataSet DataTable XML Nested Row
DataSet DataTable XML Nested Row

A lot of documentation on Microsoft’s site to XMLs and DataSets showed up, but nothing describing this problem/solution.

I am happy to say that with help from the MSDN Forums, the solution was found. Please read my post here:
http://social.msdn.microsoft.com/Forums/en-US/adodotnetdataset/thread/2d115ba6-49be-4a5c-bf92-054626109f50

So the solutions is to use the Section_Id assigned to each row in the Sections table inside the Field table’s Select() function as shown:

foreach (DataRow sectionRow in ds.Tables["Section"].Rows)
{
	string sectionId = sectionRow["Section_Id"].ToString();
	Console.WriteLine("Section: {0}", sectionRow["SectionName"]);
	foreach (DataRow fieldRow in ds.Tables["Field"].Select("Section_Id = " + sectionId))
	{
		foreach (object item in fieldRow.ItemArray)
		{
			// Do something here
		}
	}
}

This solution works for me.

Leave a Reply