Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I preserve all XML formatting with XDocument?

I'm trying to read in an XML configuration file, do a few tweaks (finding and removing or adding an element) and save it again. I want this edit to be as non-intrusive as possible since the file will be under source control and I don't want inconsequential changes to cause merge conflicts, etc. This is roughly what I've got:

XDocument configDoc = XDocument.Load(fileName, LoadOptions.PreserveWhitespace);
// modifications to configDoc here
configDoc.Save(fileName, SaveOptions.DisableFormatting);

There's a few problems that pop up here:

  1. encoding="utf-8" gets added to the xml declaration.
  2. <tag attr="val"/> gets changed to <tag attr="val" />
  3. Attributes that were spread across separate lines for readability get pushed all on to one line.

Is there any way to be less intrusive with XDocument or will I have to just try and do string editing to get what I want?

like image 677
RandomEngy Avatar asked Dec 14 '11 21:12

RandomEngy


2 Answers

The LINQ to XML object model does not store whether an element parsed is marked up as <foo/> or <foo /> so when saving back such information is lost. If you want to ensure a certain format then you could extend an XmlWriter implementation and override its http://msdn.microsoft.com/en-us/library/system.xml.xmlwriter.writeendelement.aspx but that way you would also not preserve the input format, rather you would then write out any empty elements as <foo/> or whatever format you implement in your method.

There are other changes that can happen, for instance when loading the file

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:xhtml="http://www.w3.org/1999/xhtml">
  <head>
    <title>Example</title>
  </head>
  <body>
    <h1>Example</h1>
  </body>
</html>

and saving it back the result is

<xhtml:html xmlns="http://www.w3.org/1999/xhtml" xmlns:xhtml="http://www.w3.org/1999/xhtml">
  <xhtml:head>
    <xhtml:title>Example</xhtml:title>
  </xhtml:head>
  <xhtml:body>
    <xhtml:h1>Example</xhtml:h1>
  </xhtml:body>
</xhtml:html>

so don't expect markup details to be preserved when loading/saving with XDocument/XElement.

like image 130
Martin Honnen Avatar answered Sep 23 '22 12:09

Martin Honnen


To avoid the declaration in the header of the document you can use the following

    XmlWriterSettings settings = new XmlWriterSettings();
    settings.OmitXmlDeclaration = true;


        using (XmlWriter xw = XmlWriter.Create(fileName, settings))
        {
            doc.Save(xw);
        }
like image 27
Manas Avatar answered Sep 26 '22 12:09

Manas