Search code examples
c#xmlxmlreader

Finding a value within an xml segment using XmlReader in C#


I am using XML reader to search through an xml configuration file we use. I want to find the values under a certain key and be able to change them or add if they don't exist.

XML Sample

<DBSimulatorConfigurations>
  <Configurations>
    <DBSimulatorConfiguration>
      <Key>Test1</Key>
      <Submit>0</Submit>
      <Amend>0</Amend>
      <Update>0</Update>
      <Delete>1</Delete>
    <ResponseTimeInSeconds>100</ResponseTimeInSeconds>
    </DBSimulatorConfiguration>
    <DBSimulatorConfiguration>
      <Key>Test2</Key>
      <Submit>0</Submit>
      <AutoUpdate>0</AutoUpdate>
      <Amend>0</Amend>
      <Update>0</Update>
      <Delete>1</Delete>
    <ResponseTimeInSeconds>100</ResponseTimeInSeconds>
    </DBSimulatorConfiguration>
    <DBSimulatorConfiguration>
  </Configurations> 
</DBSimulatorConfigurations>

Code so far... commented out bit doesn't find the value within 'Test1'

XmlReader reader = XmlReader.Create("C:\\<path>\\DBConfigs.xml");
while(reader.Read())
{
    if (reader.ReadToDescendant("Key"))
    {
        reader.Read();
        if (reader.Value == "Test1")
        {
            Console.WriteLine("Found_1 {0}", reader.Value);
            // Doesn't work :( 
            // reader.Read();
            //if (reader.ReadToDescendant("Submit")) {
            //  Console.WriteLine("Value for Submit is {0}", reader.Value);
            //}
        }

        if (reader.Value == "Test2")
        {
            Console.WriteLine("Found_2 {0}", reader.Value);
        }

        reader.Read(); //this moves reader to next node which is text 
        if (reader.ReadToDescendant("Full.2")) {
            Console.WriteLine("Found {0}", reader.Value);
        }

    }

But what I want to do then is find and change the value for 'Submit' or 'Amend' etc or if there is no entry 'Submit' then i'll add one.

But first i'd like to be able to find and change the values for Test1.


Solution

  • Here is one approach, using XDocument:

     string xml = @"
    <DBSimulatorConfigurations>
      <Configurations>
        <DBSimulatorConfiguration>
          <Key>Test1</Key>
          <Submit>0</Submit>
          <Amend>0</Amend>
          <Update>0</Update>
          <Delete>1</Delete>
        <ResponseTimeInSeconds>100</ResponseTimeInSeconds>
        </DBSimulatorConfiguration>
        <DBSimulatorConfiguration>
          <Key>Test2</Key>
          <Submit>0</Submit>
          <AutoUpdate>0</AutoUpdate>
          <Amend>0</Amend>
          <Update>0</Update>
          <Delete>1</Delete>
        <ResponseTimeInSeconds>100</ResponseTimeInSeconds>
        </DBSimulatorConfiguration>
        <DBSimulatorConfiguration>
        </DBSimulatorConfiguration>
      </Configurations> 
    </DBSimulatorConfigurations>";
    
    XDocument xdoc = XDocument.Parse(xml);
    //search for  all nodes with <DBSimulatorConfiguration> element
    var elements = xdoc.Root.Elements().Elements().Where(x => x.Name == "DBSimulatorConfiguration");
    //iterate through all those eleemnt
    foreach (var element in elements)
    {
        //now find it's child named Submit
        var submitElement = element.Elements().FirstOrDefault(x => x.Name == "Submit");
        //if such element is found
        if (submitElement != null)
        {
            //here you can change Submit element, like this:
            // submitElement.Value = "abc";
            //or you can check for something
            if (submitElement.ElementsBeforeSelf().Any(x=> x.Name == "Key" && x.Value== "Test2"))
            {
                //this is submitElement which is after element named Key with value Test2
                submitElement.Value = "some specific value";
            }
        }
        else
            element.Add(new XElement("Submit", 999));
    }