Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Force XmlDocument to save empty elements with an explicit closing tag

I have the following code:

string PathName = "C:\\Users\\TestUser\\Documents\\Project";
string FileName = "settings.xml";

XmlDocument Settings = new XmlDocument(); 
Settings.Load(Path.Combine(PathName, FileName));

XmlNode KnowledgeNode = Settings.SelectSingleNode("/Config/Map/Knowledge");

XmlNode UsersNode = Settings.CreateNode(XmlNodeType.Element, "Users", null);
XmlAttribute FileDirectory = Settings.CreateAttribute("FileDirectory");
FileDirectory.Value = UserSelectedFileDirectory;
UsersNode.Attributes.Append(FileDirectory);
KnowledgeNode.AppendChild(UsersNode);

Settings.Save(Path.Combine(PathName, FileName));

This results in my XML file containing <Users FileDirectory="C:\data" /> instead of <Users FileDirectory="C:\data" ></Users> as I want.

How do I create the end element? I've given it a Google and I can't find much. Any help is appreciated, thanks.

like image 521
user3277335 Avatar asked Jul 23 '17 22:07

user3277335


1 Answers

Here are three ways to force XmlDocument.Save to output a separate end tag for an empty XmlElement instead of an empty, self-closing tag.

Method 1

Insert an empty whitespace node inside the element:

UsersNode.AppendChild(Settings.CreateWhitespace(""));

Here's the output:

<Users FileDirectory="C:\data"></Users>

Method 2

Set the XmlElement.IsEmpty property of the element to false:

((XmlElement)UsersNode).IsEmpty = false;

Note that with this method, the default XML formatting settings will insert a line break between the start tag and the end tag. Here's the output:

<Users FileDirectory="C:\data">
</Users>

Method 3

Derive a custom XmlTextWriter that forwards all WriteEndElement calls to WriteFullEndElement:

public class CustomXmlTextWriter : XmlTextWriter
{
    public CustomXmlTextWriter(string fileName)
        : base(fileName, Encoding.UTF8)
    {
        this.Formatting = Formatting.Indented;
    }

    public override void WriteEndElement()
    {
        this.WriteFullEndElement();
    }
}

Usage:

using (var writer = new CustomXmlTextWriter(Path.Combine(PathName, FileName)))
{
    Settings.Save(writer);
}

This method might require less code overall if you have a lot of empty elements in your document.

As with Method 2, the default XML formatting settings will insert a line break between the start tag and end tag of each empty element.

like image 97
Michael Liu Avatar answered Oct 05 '22 22:10

Michael Liu