By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
440,213 Members | 2,108 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 440,213 IT Pros & Developers. It's quick & easy.

Help Creating XmlNode / XmlAttribute Elegantly

P: n/a
I am creating a configuration class to read / write a standard configuration file.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<add key="ConnectionString" value="server=(local);" />
</appSettings>
</configuration>

I am using a XmlDocument for my base implementation.

I am looking to see if there is a better way to add a new node / attribute than using
XmlDocument.InnerXml. I would consider this to be a hack but couldn't really see another
way of doing this without defining namespaces and the like.

I have included the full file below and the lines that I am wondering about are lines: 79, 227, and 266

Thanks,
Dave
===================================

using System;
using System.Xml;
using System.Text;

namespace Storage.Utility.Configuration
{
/// <summary>
/// Class for Reading / Writing Configuration Options
/// </summary>
public class Configuration
{
#region Data Members

private XmlDocument xmlDoc = null;
private XmlElement root = null;
private XmlNode node = null;

private string filename = null;
private string queryString = null;

#endregion

#region Constructor

public Configuration(string configFileName)
{
filename = configFileName;
}

#endregion

#region Methods

#region Miscellaneous

/// <summary>
/// Initialize the Configuration Class
/// </summary>
private void Initialize()
{
LoadConfiguration();
}

#endregion

#region File Access

/// <summary>
/// Reload the Configuration File
/// </summary>
public void ReloadConfiguration()
{
LoadConfiguration();
}
/// <summary>
/// Save the Configuration File
/// </summary>
public void Save()
{
SaveConfiguration();
}
/// <summary>
/// Load the Configuration File
/// </summary>
private void LoadConfiguration()
{
try
{
xmlDoc = new XmlDocument();
xmlDoc.Load(filename);
}
catch (Exception)
{
// Create Configuration File
xmlDoc.InnerXml = "<?xml version=\"1.0\" encoding=\"utf-8\"?><configuration></configuration>";
}
finally
{
root = xmlDoc.DocumentElement;
}
}
/// <summary>
/// Save the Configuration File
/// </summary>
private void SaveConfiguration()
{
try
{
xmlDoc.Save(filename);
}
catch (Exception ex)
{
// Can't do anything
throw (ex);
}
}

#endregion

#region Retrieve Values

/// <summary>
/// Get the Value of the Key
/// </summary>
/// <param name="section"></param>
/// <param name="key"></param>
/// <returns></returns>
public string GetValue(string section, string key)
{
try
{
// Find the Node
node = GetValueNode(section, key);
if (node != null)
{
// Retrieve Value
XmlNode valueNode = node.Attributes.GetNamedItem("value");
return (valueNode.Value);
}
}
catch (Exception)
{
// Nothing to do
}

// Error Occurred
return (null);
}
/// <summary>
/// Find the Node that the Key belongs to
/// </summary>
/// <param name="section"></param>
/// <param name="key"></param>
/// <returns></returns>
private XmlNode GetValueNode(string section, string key)
{
try
{
// XML Search Path
queryString = "/configuration/" + section + "/add[@key=\"" + key + "\"]";

// Look from the Root of the Document
return (root.SelectSingleNode(queryString));
}
catch (Exception)
{
// Nothing to do
}

// Error Occurred
return (null);
}

#endregion

#region Store Values

/// <summary>
/// Store Key / Value in Configuration File
/// </summary>
/// <param name="section"></param>
/// <param name="key"></param>
/// <param name="keyValue"></param>
/// <returns></returns>
public bool StoreValue(string section, string key, string keyValue)
{
try
{
// Find Node if it exists
node = GetValueNode(section, key);
if (node != null)
{
// Update Value
node = node.Attributes.GetNamedItem("value");
node.Value = keyValue;
return (true);
}

// Node Doesn't Exist -> Get/Create Section -> Add Key / Value
if (GetSection(section) == true)
return (CreateValueNode(section, key, keyValue));
}
catch (Exception)
{
// Nothing to do
}

// Error Occurred
return (false);
}

#endregion

#region Create Nodes

/// <summary>
/// Create New Key / Value Entry
/// </summary>
/// <param name="section"></param>
/// <param name="key"></param>
/// <param name="keyValue"></param>
/// <returns></returns>
private bool CreateValueNode(string section, string key, string keyValue)
{
try
{
// Get Section
queryString = "/configuration/" + section;
node = root.SelectSingleNode(queryString);

// Node Must Exist
if (node != null)
{
// Create and Add New Key / Value Entry
StringBuilder sb = new StringBuilder(500);
sb.Append("<add key=\""); sb.Append(key); sb.Append("\" ");
sb.Append("value=\""); sb.Append(keyValue); sb.Append("\" />");

node.InnerXml += sb.ToString();
return (true);
}
}
catch (Exception)
{
// Nothing to do
}

// Error Occurred
return (false);
}
/// <summary>
/// Get / Create a New Configuration Section
/// </summary>
/// <param name="section"></param>
/// <returns></returns>
private bool GetSection(string section)
{
try
{
// Does the Section Exist
queryString = "/configuration/" + section;
node = root.SelectSingleNode(queryString);
if (node != null)
return (true);

// Get the Configuration Node
queryString = "/configuration";
node = root.SelectSingleNode(queryString);
if (node != null)
{
// Create a New Section
StringBuilder sb = new StringBuilder(1000);
sb.Append("<"); sb.Append(section); sb.Append(">");
sb.Append("</"); sb.Append(section); sb.Append(">");

node.InnerXml += sb.ToString();
return (true);
}
}
catch (Exception)
{
// Nothing to do
}

// Error Occurred
return (false);
}
#endregion

#endregion

} // Class
}

Nov 12 '05 #1
Share this Question
Share on Google+
2 Replies


P: n/a
"David Elliott" <We*****@newsgroups.nospam> wrote in message news:2b********************************@4ax.com...
I am looking to see if there is a better way to add a
new node / attribute than using XmlDocument.InnerXml. : : but couldn't really see another way of doing this without
defining namespaces and the like.
The example XML you've given doesn't contain any namespaces,
so why should you define one?

Have a look at the CreateElement() and CreateAttribute()
methods of XmlDocument, and then AppendChild() on XmlNode
(and remember that XmlDocument is an XmlNode, so it also
allows you to AppendChild() nodes to it).
the lines that I am wondering about are lines: 79, 227,
and 266

79: xmlDoc.InnerXml = "<?xml version=\"1.0\" encoding=\"utf-8\"?><configuration></configuration>";

If you set UTF-8 Encoding on an I/O Stream wrapped by an
XmlTextWriter (or TextWriter), this XML declaration will
be emitted for you automatically.

Here's how you'd create a custom XmlDeclaration for the
XmlDocument (note that if you do Save this XML to a
TextWriter-based class, its Encoding takes precedence).

XmlDeclaration xmlDecl = xmlDoc.CreateXmlDeclaration("1.0", "utf-8", "");

Then you'd want to create your <configuration> element.

XmlElement eRoot = xmlDoc.CreateElement( "configuration");

Finally, add the root element to XmlDocument and insert
the XmlDeclaration before it,

xmlDoc.AppendChild( eRoot);
xmlDoc.InsertBefore( xmlDecl, eRoot);
: :
223: StringBuilder sb = new StringBuilder(500);
224: sb.Append("<add key=\""); sb.Append(key); sb.Append("\" ");
225: sb.Append("value=\""); sb.Append(keyValue); sb.Append("\" />");
226:
227: node.InnerXml += sb.ToString();

XmlElement eAdd = xmlDoc.CreateElement( "add");
eAdd.SetAttribute( "key", key);
eAdd.SetAttribute( "value", keyValue);
node.AppendChild( eAdd);
: :
264: sb.Append("</"); sb.Append(section); sb.Append(">");
265:
266: node.InnerXml += sb.ToString();

Your example code never gives a value to the argument,
section, but from your example XML I'll guess it's
<appSettings> (although I don't see where you have
inserted the child node between the start and end
elements).
XmlElement eAppSettings = xmlDoc.CreateElement( "appSettings");
eAppSettings.AppendChild( eAdd);
eRoot.AppendChild( eAppSettings);
These three statements essentially tie together the
entire configuration document's XML nodes.

It looks like you own (because you want to own?) the
entire configuration file, but I'll also point out that
in the .NET Framework's System.Configuration namespace
are classes automatically supporting this configuration
schema to read a config file from "application.exe.config"
or "web.config".

Using the built-in configuration file support allows you
to create the element,

<add name="key" value="keyValue" />

in a single statement like this,

ConfigurationSettings.AppSettings[ key] = keyValue;

with the default NameValueSectionHandler.

Derek Harmon
Nov 12 '05 #2

P: n/a
Thanks,
Dave

"Derek Harmon" wrote:
"David Elliott" <We*****@newsgroups.nospam> wrote in message news:2b********************************@4ax.com...
I am looking to see if there is a better way to add a
new node / attribute than using XmlDocument.InnerXml.

: :
but couldn't really see another way of doing this without
defining namespaces and the like.


The example XML you've given doesn't contain any namespaces,
so why should you define one?

Have a look at the CreateElement() and CreateAttribute()
methods of XmlDocument, and then AppendChild() on XmlNode
(and remember that XmlDocument is an XmlNode, so it also
allows you to AppendChild() nodes to it).
the lines that I am wondering about are lines: 79, 227,
and 266

79: xmlDoc.InnerXml = "<?xml version=\"1.0\" encoding=\"utf-8\"?><configuration></configuration>";

If you set UTF-8 Encoding on an I/O Stream wrapped by an
XmlTextWriter (or TextWriter), this XML declaration will
be emitted for you automatically.

Here's how you'd create a custom XmlDeclaration for the
XmlDocument (note that if you do Save this XML to a
TextWriter-based class, its Encoding takes precedence).

XmlDeclaration xmlDecl = xmlDoc.CreateXmlDeclaration("1.0", "utf-8", "");

Then you'd want to create your <configuration> element.

XmlElement eRoot = xmlDoc.CreateElement( "configuration");

Finally, add the root element to XmlDocument and insert
the XmlDeclaration before it,

xmlDoc.AppendChild( eRoot);
xmlDoc.InsertBefore( xmlDecl, eRoot);
: :
223: StringBuilder sb = new StringBuilder(500);
224: sb.Append("<add key=\""); sb.Append(key); sb.Append("\" ");
225: sb.Append("value=\""); sb.Append(keyValue); sb.Append("\" />");
226:
227: node.InnerXml += sb.ToString();

XmlElement eAdd = xmlDoc.CreateElement( "add");
eAdd.SetAttribute( "key", key);
eAdd.SetAttribute( "value", keyValue);
node.AppendChild( eAdd);
: :
264: sb.Append("</"); sb.Append(section); sb.Append(">");
265:
266: node.InnerXml += sb.ToString();

Your example code never gives a value to the argument,
section, but from your example XML I'll guess it's
<appSettings> (although I don't see where you have
inserted the child node between the start and end
elements).
XmlElement eAppSettings = xmlDoc.CreateElement( "appSettings");
eAppSettings.AppendChild( eAdd);
eRoot.AppendChild( eAppSettings);
These three statements essentially tie together the
entire configuration document's XML nodes.

It looks like you own (because you want to own?) the
entire configuration file, but I'll also point out that
in the .NET Framework's System.Configuration namespace
are classes automatically supporting this configuration
schema to read a config file from "application.exe.config"
or "web.config".

Using the built-in configuration file support allows you
to create the element,

<add name="key" value="keyValue" />

in a single statement like this,

ConfigurationSettings.AppSettings[ key] = keyValue;

with the default NameValueSectionHandler.

Derek Harmon

Nov 12 '05 #3

This discussion thread is closed

Replies have been disabled for this discussion.