10

I need to comment and uncomment the 4th line of this XML file using System.XML properties:

<?xml version="1.0" encoding="utf-8"?>
    <configuration>    
        <system.web>
            <customErrors mode="On" defaultRedirect="som_url_here" />
        </system.web>
    </configuration>

Desired output:

<!-- <customErrors mode="On" defaultRedirect="som_url_here" /> -->

It's possible to achieve this without using a file reader?

The node:

XmlNode xmlNodoCE = docWebConfig.DocumentElement.SelectSingleNode("system.web/customErrors");
Otto
  • 4,020
  • 6
  • 35
  • 46
  • 2
    How would you expect to do this without reading the file? – Jeff Mercado Jun 13 '11 at 08:45
  • With System.XML if its possible. – Otto Jun 13 '11 at 08:46
  • System.XML doesn't let you magically transform the file without reading it. – Bertrand Marron Jun 13 '11 at 08:47
  • 2
    Why not use a different web.config? – Stuart Grassie Jun 13 '11 at 08:50
  • 1
    Would you not be better of using config transformation files? http://msdn.microsoft.com/en-us/library/dd465326.aspx – Richard Forrest Jun 13 '11 at 08:52
  • Maybe with this http://msdn.microsoft.com/en-us/library/system.xml.xmltextwriter(v=VS.90).aspx? – Otto Jun 13 '11 at 08:58
  • 1
    how about http://msdn.microsoft.com/en-us/library/system.xml.xmldocument.createcomment(v=VS.100).aspx for commenting. And here is question about uncommenting http://stackoverflow.com/questions/3677016/to-uncomment-a-commented-node-in-a-xml-file-using-c – Andrej Slivko Jun 13 '11 at 09:00
  • 1
    In your comment below *"i need to conserve the value of defaultRedirect="" when i want to set it to false again"*, you do realise that if you're doing this within the application and you modify the `web.config` file your app will restart? – Kev Jun 13 '11 at 09:15
  • @Kev The IT guys told me that I should avoid that issue bacause they manage it with IIS. – Otto Jun 13 '11 at 11:41

3 Answers3

12

You need to

  • load the file into an XmlDocument,
  • retrieve the node you want to comment,
  • create a comment node containing the XML content of your original node,
  • add this comment to the original's parent node just before the original node
  • remove it from its parent,
  • write the XmlDocument to a file (the same one).

    String xmlFileName = "Sample.xml";
    
    // Find the proper path to the XML file
    String xmlFilePath = this.Server.MapPath(xmlFileName);
    
    // Create an XmlDocument
    System.Xml.XmlDocument xmlDocument = new System.Xml.XmlDocument();
    
    // Load the XML file in to the document
    xmlDocument.Load(xmlFilePath);
    
    // Get the target node using XPath
    System.Xml.XmlNode elementToComment = xmlDocument.SelectSingleNode("/configuration/system.web/customErrors");
    
    // Get the XML content of the target node
    String commentContents = elementToComment.OuterXml;
    
    // Create a new comment node
    // Its contents are the XML content of target node
    System.Xml.XmlComment commentNode = xmlDocument.CreateComment(commentContents);
    
    // Get a reference to the parent of the target node
    System.Xml.XmlNode parentNode = elementToComment.ParentNode;
    
    // Replace the target node with the comment
    parentNode.ReplaceChild(commentNode, elementToComment);
    
    xmlDocument.Save(xmlFilePath);
    
Samu Lang
  • 2,261
  • 2
  • 16
  • 32
  • This is a bit specific to your xml file. In general you'd need to keep track of the position of the original target node and insert the new comment node in the same position. Let me know if you need that as well. – Samu Lang Jun 13 '11 at 09:14
  • @langsamu But it appends to the end, is there any way to put it where it should be? I mean, put the commented line under his own comment of the XML file. – Otto Jun 13 '11 at 10:37
  • I don't quite understand. Can you post original and desired XML. – Samu Lang Jun 14 '11 at 13:47
  • @langsamu I have more nodes under and i want to comment the line and have it where it was in the same node tree, not to append it to the end of the tree – Otto Jun 15 '11 at 11:34
  • OK. You need to use InsertBefore instead of AppendChild. First create the comment node, then insert the comment node to the parent node before the original node, and finally remove the original node. I'll edit the answer in a sec. – Samu Lang Jun 15 '11 at 12:08
  • @langsamu Actually im using prepend instead of append – Otto Jun 15 '11 at 12:10
  • 1
    That would make it always the first instead of always the last. The proper solution is as per my previous comment and the edited answer. – Samu Lang Jun 15 '11 at 12:14
4

This should do the trick. It is a console app, but the principle is exactly the same. It does assume a file called "web.config" will be in the same folder as the exe:

using System;
using System.Xml;

namespace ConsoleApplication7
{
    class Program
    {
        static void Main(string[] args)
        {
            var document = new XmlDocument();
            document.Load("web.config");

            var element = document.SelectSingleNode("//compilation[@defaultLanguage = 'c#' and @debug = 'true']");

            var comment = document.CreateComment(element.OuterXml);

            element.ParentNode.ReplaceChild(comment, element);

            document.Save("web.config2");

            var document2 = new XmlDocument();
            document2.Load("web.config2");

            var comment2 = document2.SelectSingleNode("//system.web/comment()");
            var newNode = document2.CreateDocumentFragment();
            newNode.InnerXml = comment2.InnerText;
            comment2.ParentNode.ReplaceChild(newNode, comment2);
            document2.Save("web.config3");

            Console.ReadKey();
        }
    }
}

It's saving to different files to show the progression of the xml, obviously, you'd just want to save back to the original file.

edit: You changed the xml since I wrote the answer, but if you change the xpath then it should work exactly the same.

Stuart Grassie
  • 3,043
  • 1
  • 27
  • 36
-2

the problem here is that an XmlDocument is a data structure for a load of XML, it will not read in the comments when it parses the file. you are trying to edit the file itself.

harryovers
  • 3,087
  • 2
  • 34
  • 56