Read xml file using System.XML namespace

1.5k views Asked by At

I want to read the <appSettings> section of the App.config file using my own xml code (not linq to xml):

Here's my app.config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>   
<appSettings>
    <add key="driver" value="C:/"/>
    <add key="daysToExpire" value="0"/>
    <add key="Interval" value="5000"/>
</appSettings>
<system.net>
    <mailSettings >
        <smtp>
            <network enableSsl="false" 
                     port="25"
                     host="smtp.gmail.com"
                     defaultCredentials="false"
                     />

        </smtp>
    </mailSettings>
</system.net>

My c# code:

XmlDocument doc = new XmlDocument();
doc.Load(
    Path.Combine(AppDomain.CurrentDomain.BaseDirectory,    "config.xml")
);

XmlNodeList appSettings = doc.SelectNodes("/configuration/appSettings/add");

Driver = appSettings[0].Attributes[0].Value;
Interval = Convert.ToInt16(appSettings[2].Value);
DaysToExpire = Convert.ToInt16(appSettings[1].Value);

appSettings has 3 modes but I didn't manage to access each one.

I also want to read the system.net section.

3

There are 3 answers

0
Gary Walker On

If you just want to read the app.config settings, use the configuration manager. If you are trying to learn how to use XmlDocument, you have a few problems.

1) You really should not depend upon the order of nodes within an XML document in the general case, you have more stable code if you parse depending upon the XML content. This is not your actual problem.

2) Considering the node  <add key="daysToExpire" value="0"/>  

This is actually an XmlElement node. It contains 2 XmlAttribute nodes. It does not have a Value. Actually, en XmlElement node never have a Value (the .Value property will always be null). A "value" in an XmlElement will be the .InnerText (or .InnerXml) property.

If you look at your code, you correctly read the driver value as an Attribute, but you did not do so for the other two nodes. You still have the problem of retrieving the attribute based on the index instead of the attribute name. Using the name is a more stable parsing technique.

0
MarcinJuraszek On

LINQ to XML way:

var xDoc = XDocument.Load("Input.txt");

var appSettings = xDoc.Root.Element("appSettings");
var driver = (string)appSettings.Elements("add")
                                .First(x => (string)x.Attribute("key") == "driver")
                                .Attribute("value");
var daysToExpire = (string)appSettings.Elements("add")
                                      .First(x => (string)x.Attribute("key") == "daysToExpire")
                                      .Attribute("value");
var interval = (string)appSettings.Elements("add")
                                  .First(x => (string)x.Attribute("key") == "Interval")
                                  .Attribute("value");

You need using System.Linq and using System.Xml.Linq at the top of the file to make it work.

But to be honest: you should use AppSettings, because it's designed for that.

0
Sergey Berezovskiy On

Let me explain why parsing appSettings manually is not very good idea. Besides add elements appSettings can contain clear and remove elements, which affect affect previously defined settings. So, with following section:

<appSettings>
  <add key="driver" value="C:/"/>
  <clear/>
  <add key="daysToExpire" value="0"/>    
  <add key="Interval" value="5000"/>
  <remove key="daysToExpire"/>
</appSettings>

You will have only one setting (Interval) defined for your application. If you will try to get all add elements, you will get incorrect settings (all three elements will be in dictionary):

var configPath = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
var xdoc = XDocument.Load(configPath);
var appSettings = xdoc.Root.Element("appSettings").Elements("add")
                      .ToDictionary(a => (string)a.Attribute("key"),
                                    a => (string)a.Attribute("value"));

Correct parsing will look like:

var appSettings = new Dictionary<string, string>();
foreach(var e in xdoc.Root.Element("appSettings").Elements())
{
    switch(e.Name.LocalName)
    {
        case "add":
            appSettings.Add((string)e.Attribute("key"), 
                            (string)e.Attribute("value"));
            break;
        case "clear":
            appSettings.Clear();
            break;
        case "remove":
            appSettings.Remove((string)e.Attribute("key"));
            break;
    }
}

On the other hand, ConfigurationManager is already here and it can parse application settings correctly. Following code will print out single Interval setting:

foreach(string key in ConfigurationManager.AppSettings)
    Console.WriteLine("{0}: {1}", key, settings[key]);

Also keep in mind, that actual settings of your application will also contain settings from machinne.config file. ConfigurationManager will also get those settings for you.