0
<?xml version="1.0" encoding="utf-8"?>
 <configSections>
    ----------
    ----------
 </configSections>
 <appSettings>
     <add key="Name" Value="XXX">
     <add key="Age" Value="10">
     <!--<add key="Number" value="5"/>--><!--uncomment it-->
     <!--<add key="Class" value="10"/>-->
 </appSettings>

I want to uncomment the first commented line.

That's my code so far:

foreach (XmlElement xElement in xmlDoc.DocumentElement)
{
    if (xElement.Name == "appSettings")
    {
        foreach (XmlNode xNodes in xElement.ChildNodes)
        {
            if (xNodes.NodeType == XmlNodeType.Comment)
            {
                if (xNodes.InnerText.Contains("Number"))
                {
                    // Now the commented line is in xNodes.InnerText.
                    // How can i add this line in that xml file under appSettings?
                }
            }
        }
        break;
    }
}
Daniel Hilgarth
  • 171,043
  • 40
  • 335
  • 443
Karthick
  • 256
  • 1
  • 4
  • 13
  • 1
    do you mean to read the "Name" key? what do you mean by saying that you want to add a read line under appsettings element? – Kishore Borra Aug 29 '12 at 10:56
  • Are you trying to uncomment that line? – Daniel Hilgarth Aug 29 '12 at 10:57
  • Really hard to understand. Please reformulate your question. – Renatas M. Aug 29 '12 at 10:58
  • @danielhilgarth Yes. I want to uncomment. – Karthick Aug 30 '12 at 05:42
  • @grkkarthick: Alright. Please show the code you have so far. – Daniel Hilgarth Aug 30 '12 at 06:39
  • @DanielHilgarth foreach (XmlElement xElement in xmlDoc.DocumentElement) { if (xElement.Name == "appSettings") { foreach (XmlNode xNodes in xElement.ChildNodes) { if (xNodes.NodeType == XmlNodeType.Comment) { if (xNodes.InnerText.Contains("Number")) { //now the commented line is in xNodes.InnerText. How can i add this line in that xml file under appSettings? } } } break; } } – Karthick Aug 31 '12 at 05:28
  • @grkkarthick: Are you attempting to modify your own app.config? Are you aware of the fact that it isn't really supported to do so? The changes will only come into effect after you restart your program – Daniel Hilgarth Aug 31 '12 at 06:11
  • @DanielHilgarth No i'm going to edit in another app.exe.config file. Not in my own app.config file. – Karthick Aug 31 '12 at 07:20

3 Answers3

1

You can use this code:

var appSettingsNode = xmlDoc.DocumentElement
                            .ChildNodes
                            .Cast<XmlNode>()
                            .FirstOrDefault(x => x.Name == "appSettings");

if(appSettingsNode == null)
    return;

var commentedNodes = appSettingsNode.ChildNodes
                                    .Cast<XmlNode>()
                                    .Where(x => x.NodeType == XmlNodeType.Comment
                                                && (x.InnerText.Contains("Number")
                                                    || x.InnerText.Contains("Class")))
                                    .ToList();

foreach(var commentedNode in commentedNodes)
{
    var tmpDoc = new XmlDocument();
    tmpDoc.LoadXml(commentedNode.InnerText);
    appSettingsNode.ReplaceChild(xmlDoc.ImportNode(tmpDoc.DocumentElement, true),
                                 commentedNode);

    // Use this instead if you want to keep the commented line:
    // appSettingsNode.AppendChild(xmlDoc.ImportNode(tmpDoc.DocumentElement, true));
}

The important part is the one inside the foreach loop.
Here we load the commented node into a new XmlDocument (tmpDoc) to get it as a "real" XmlNode back. Then we simply replace the comment node (commentedNode) with our newly loaded node (tmpDoc.DocumentElement).

The rest is your original code, just beautified. Please note how I reduced the cyclomatic complexity by replacing the loops and ifs with LINQ queries.

Daniel Hilgarth
  • 171,043
  • 40
  • 335
  • 443
  • Thank you Daniel!!! Great its working well. I have another doubt. How can I include one more key? Should I write the about commentNode line again with a new key? @DanielHilgarth – Karthick Aug 31 '12 at 09:36
  • @grkkarthick: Please check update. For multiple keys, we need to use a `foreach` loop and change the second LINQ query a bit. – Daniel Hilgarth Aug 31 '12 at 09:41
  • Thank you man. Great work. I had struggled with this from the past two weeks. – Karthick Aug 31 '12 at 10:00
  • I think there is one extra ')' in the commentedNodes variable at last. – Karthick Aug 31 '12 at 11:22
  • @grkkarthick: Fixed. The problem wasn't a `)` but two different names for the same variable `commentNode` inside the loop vs `commentedNode` in the loop header. – Daniel Hilgarth Aug 31 '12 at 11:26
  • Sorry cannot get your answer. – Karthick Aug 31 '12 at 11:27
  • ya get it. but i didnot use '(' after &&. will it make any mistake? I hope it does not a bug. – Karthick Aug 31 '12 at 11:32
  • @grkkarthick: It will make a difference, you need to add the parenthesis where I put it. Otherwise you will also get nodes that contain `"Class"` but are not comment nodes. Note, `&&` has a higher precedence than `||`: `(false && false || true) != (false && (false || true))` – Daniel Hilgarth Aug 31 '12 at 11:44
  • I have a issue with this. When i debug the second one does not get updated. It is still in commented line. :( @Daniel – Karthick Aug 31 '12 at 13:28
  • @grkkarthick: Please see update. The second query was missing a `ToList` at the end. – Daniel Hilgarth Aug 31 '12 at 13:41
  • @grkkarthick: LINQ queries internally use the [`yield` keyword](http://msdn.microsoft.com/en-us/library/9k7k7cf0.aspx) to support deferred execution. In our case, it means that without `ToList` the query won't be executed at the line it is defined, but it will be executed when using the result in the `foreach` loop. It will go something like this: (1) get and return first result of query. (2) execute our loop body (3) get and return second result of query (4) execute our loop body. The second result is requested from the already changed `xmlDoc` instance, leading to incorrect results. – Daniel Hilgarth Sep 03 '12 at 07:34
0

If you want to read Name key this is how you do:

string myUsername = System.Configuration.ConfigurationManager.AppSettings["Name"];
Kishore Borra
  • 269
  • 3
  • 15
0

In C# .net you would usually use System.Configuration.ConfigurationManager.AppSettings to read an appSetting from the config file.

If you are trying to read the commented out line from the web.config then you are going to have to write some custom code to do this.

This answer should give you a good head start

Community
  • 1
  • 1
shenku
  • 11,969
  • 12
  • 64
  • 118