Search code examples
c#xmllinqxpathxmldocument

How to access different XML nodes which have same parent?


I have a XML file like this:

<Document>
   <Tests>
      <Test>
          <Name>A</Name>
          <Value>1</Value>
      </Test>
      <Test>
          <Name>A</Name>
          <Value>2</Value>
      </Test>
      <Test>
          <Name>B</Name>
          <Value>10</Value>
      </Test>
      <Test>
          <Name>B</Name>
          <Value>20</Value>
      </Test>
   </Tests>
</Document>

I made a class to hold data for each Test node:

public class TestData
{
public string TestName {get; set;}
public float TestValue {get; set;}
}

And I read the data using XPATH like this (ztr is instance of XmlDocument And I already know the name of Test I am going to read, since it was populted into a ListView):

    public TestData GetTestData(string testName)
    {
        TestData data = new TestData();           

        data.TestName = testName;
        data.TestValue = float.Parse(ztr.SelectSingleNode("/Document/Tests/Test[Name = '" + testName + "')]/Value").InnerText, CultureInfo.InvariantCulture);

        return data;
    }

Now, te problem is that if I want to make a list of data as List<TestData> each TestData only refers to the first occurance of the Test node in the XML file. What I mean is lets imagin I have a ListView that is already populated by name of all Test nodes in my xml file. that is something like this in this case:

ListView = A,A,B,B and then I copy all names to a string[] array

And I use this code to read them all in one go:

private List<TestData> GetAllData()
{
    List<TestData> Datas = new List<TestData>();
    TestData data;

    foreach(string test in stringOfNames)
    {
       data = new TestData;
       data = GetTestData(test);
       Datas.add(data);
    }

    return Datas
}

As I told you This code does not make any distinguish between different Test. It just returns the first occurance of a Test so the result for GetAllData() will be:

Name     Value
A        1
A        1
B        10
B        10

BUT I want it to be like

Name     Value
A        1
A        2
B        10
B        20

Can you please tell me what I am doing wrong? and how to solve this problem?

P.S. I wrote all the codes just here in stackoverflow...they are not compiled, just imagine they work fine :D


Solution

  • Modify your GetTestData() method (and its caller accordingly):

        public TestData GetTestData(string testName, int pos) 
        { 
            TestData data = new TestData();            
    
            data.TestName = testName; 
            data.TestValue 
             = float.Parse(
    ztr.SelectSingleNode("/Document/Tests/Test[Name = '" + testName + "')][" + pos + "]/Value").InnerText, CultureInfo.InvariantCulture); 
    
            return data; 
        }