Search code examples
c#asp.netxmlxml-parsingxmldocument

How to loop through XML document nodes to store values with XPath


I am trying to loop through an XML document as follows:

<proposer driverId="1">
    <conviction convictionId="1">
      <code>16</code>
    </conviction>
    <conviction convictionId="2">
      <code>10</code>
    </conviction>
</proposer>
<driver driverId="2">
    <conviction convictionId="3">
      <code>22</code>
    </conviction>
</driver>

My idea is to take all the convictions code whether it is proposer or driver and store it in a list of strings then by sending an index, I am performing ElementAtOrDefault to get the code.

DrivingConvictionCode1 = GetConvictionCode(1, risk);
DrivingConvictionCode2 = GetConvictionCode(2, risk);
DrivingConvictionCode3 = GetConvictionCode(3, risk);

Here in the GetConvictionCode method, I am passing Index values along with XmlDoc which calls the GetConvictions method and then performs ElementAtOrDefault to get ConvictionCode based on the index.

private string GetConvictionCode(int convictionSrNo, XmlDocument risk)
{
    var convictions = GetConvictions(risk);
    return convictions.ElementAtOrDefault(convictionSrNo - 1) == null ? string.Empty : convictions[convictionSrNo - 1];
}

private List<string> GetConvictions(XmlDocument risk)
{
    var convictions = new List<string>();
    foreach (XmlNode selectNode in risk.SelectNodes("/risk/proposer/conviction"))
    {
        convictions.AddRange(new[] {selectNode.SelectSingleNode("/risk/proposer/conviction/code").InnerText});
    }
    foreach (XmlNode selectNode in risk.SelectNodes("/risk/driver/conviction"))
    {
        convictions.AddRange(new[] {selectNode.SelectSingleNode("/risk/driver/conviction/code").InnerText});
    }
    return convictions;
}

The issue I am facing here is in the loop, the next conviction value is getting replaced by the old one. The value in the first loop is 16, and the next value should be 10 but it's coming as 16. Can anybody help out or tell me any other way?

The output I expect is:

DrivingConvictionCode1 = GetConvictionCode(1, risk); // 16
DrivingConvictionCode2 = GetConvictionCode(2, risk); // 10
DrivingConvictionCode3 = GetConvictionCode(3, risk); // 22

Solution

  • Solution 1

    1. Provide the XPath: "/risk/proposer/conviction/code" and "/risk/driver/conviction/code".

    2. Use InnerText instead of .SelectSingleNode("<path>").InnerText to get the value.

    foreach (XmlNode selectNode in risk.SelectNodes("/risk/proposer/conviction/code"))
    {
        convictions.AddRange(new[] { selectNode.InnerText });
    }
    
    foreach (XmlNode selectNode in risk.SelectNodes("/risk/driver/conviction/code"))
    {
        convictions.AddRange(new[] { selectNode.InnerText });
    }
    

    Solution 2

    Work with .SelectSingleNode("code").

    foreach (XmlNode selectNode in risk.SelectNodes("/risk/proposer/conviction"))
    {
        convictions.AddRange(new[] { selectNode.SelectSingleNode("code").InnerText });
    }
    
    foreach (XmlNode selectNode in risk.SelectNodes("/risk/driver/conviction"))
    {
        convictions.AddRange(new[] { selectNode.SelectSingleNode("code").InnerText });
    }