Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add XElement to XML file with formatting and indenting

XML

Source XML

<!-- The comment -->
<Root xmlns="http://www.namespace.com">
    <FirstElement>
    </FirstElement>

    <SecondElement>
    </SecondElement>
</Root>

Desired XML

<!-- The comment -->
<Root xmlns="http://www.namespace.com">
    <FirstElement>
    </FirstElement>

    <SecondElement>
    </SecondElement>

    <ThirdElement>
        <FourthElement>thevalue</FourthElement>
    </ThirdElement>
</Root>

Now my output XML is

<!-- The comment -->
<Root xmlns="http://www.namespace.com">
    <FirstElement>
    </FirstElement>

    <SecondElement>
    </SecondElement><ThirdElement><FourthElement>thevalue</FourthElement></ThirdElement>
</Root>

Note that I need to load the XML with LoadOptions.PreserveWhitespace as I need to preserve all whitespaces (desired by customer). The desired output is to put 2 newlines after the last child element of the "root" and add with the proper indent

<ThirdElement>
    <FourthElement>thevalue</FourthElement>
</ThirdElement>

Any ideas how to realize this?

Code

var xDoc = XDocument.Load(sourceXml, LoadOptions.PreserveWhitespace); //need to preserve all whitespaces
var mgr = new XmlNamespaceManager(new NameTable());
var ns = xDoc.Root.GetDefaultNamespace();
mgr.AddNamespace("ns", ns.NamespaceName);

if (xDoc.Root.HasElements)
{
    xDoc.Root.Elements().Last().AddAfterSelf(new XElement(ns + "ThirdElement", new XElement(ns + "FourthElement", "thevalue")));

    using (var xw = XmlWriter.Create(outputXml, new XmlWriterSettings() { OmitXmlDeclaration = true })) //omit xml declaration
        xDoc.Save(xw);
}
like image 924
BertAR Avatar asked Mar 06 '23 20:03

BertAR


2 Answers

Ideally, you should explain to your client that this really isn't important.

However, if your really need to mess around with whitespace, i'd note that XText is what you need. This is another XObject that represents text nodes and can be interspersed as part of your content. This is probably a much better approach than string manipulation.

For example:

doc.Root.Add(
    new XText("\n\t"),
    new XElement(ns + "ThirdElement",
        new XText("\n\t\t"),
        new XElement(ns + "FourthElement", "thevalue"),
        new XText("\n\t")),
    new XText("\n"));

See this demo.

like image 148
Charles Mager Avatar answered Mar 14 '23 21:03

Charles Mager


My solution is to beautify just before saving by reparsing the document.

string content = XDocument.Parse(xDoc.ToString()).ToString();
File.WriteAllText(file, content, Encoding.UTF8);
like image 27
Beauty Avatar answered Mar 14 '23 21:03

Beauty