Introducción:
Esta clase (ConfigXml) es la versión para Visual Studio .NET 2003 de la
que ya publiqué para Visual Studio 2005 (versión de
Visual Basic y versión
para C#), para
ver con detalle que funcionalidad ofrece esta clase, pulsa en cualquiera de los dos links
anteriores.
Actualizado 12/Ene/2008:
He publicado una
actualización del código para Visual Basic 2005/2008
IMPORTANTE:
Lo que si te quiero aclarar, es que esta clase NO se puede usar para leer y guardar los datos
generados por el Visual Studio en el fichero app.config, si quieres esa funcionalidad (o casi),
puedes usar la versión anterior.
Tal como te digo en la advertencia anterior, esta clase NO vale para
compatibilizar los ficheros creados por Visual Studio, sino para crear tus propios ficheros en
los que guardar los datos de configuración.
El formato usado es XML guardados con la codificación UTF-8, por tanto si la modificas
manualmente asegúrate de que se guarda en ese formato, sino seguramente recibirás un error al
acceder al fichero, esto no es fallo de la clase, es algo que ocurre siempre que trabajemos con
el formato UTF-8 y después no lo guardemos en ese formato.
La diferencia principal con la versión para Visual Studio 2005, es que en
aquella se usan colecciones de tipo generic para devolver las secciones, y en esta
versión y debido a que Visual Studio .NET 2003 no sabe nada de generics, pues utilizo
colecciones de tipo StringCollection para devolver las secciones (método Secciones) y una
colección de tipo StringDictionary para devolver las claves y valores de la sección
indicada (método Claves).
Por lo demás, el código es exactamente el mismo que para las versiones de los hermanos mayores.
En el ZIP puedes ver el código completo de un ejemplo de cómo usar la clase,
(con comentarios más o menos detallados de lo que se hace en cada caso), tanto para Visual Basic .NET 2003 como para Visual C# 2003, además el código fuente de la clase te lo muestro un poco más abajo, también para Visual Basic
como para C#.
Por supuesto, ese mismo código es válido para cualquier versión de .NET, aunque
si quieres usar las clases especialmente creadas para la versión 2005 de Visual Studio, usa los
links que hay al principio.
Como de costumbre, espero que te sea de utilidad.
Nos vemos.
Guillermo
P.S.
Esta clase la he usado por primera vez en la utilidad para
"filtrar" los ficheros de Word para usar en las colaboraciones, al menos para usarla con
Visual Studio .NET 2003.
Nota (14/Sep/07):
Si quieres guardar correctamente tipos de datos Font y Color, puedes usar
la actualización para Visual Basic que ha hecho Antonio R.
Fernandez.
El código para Visual Basic .NET
(cualquier versión)
|
'------------------------------------------------------------------------------
' Clase para manejar ficheros de configuración (17/Ago/06)
'
' Versión para Visual Basic 2003 basada en la clase de Visual Basic 2005
'
' ©Guillermo 'guille' Som, 2005-2006
'------------------------------------------------------------------------------
Option Explicit On
Option Strict On
Imports Microsoft.VisualBasic
Imports System
Imports System.Collections
Imports System.Collections.Specialiced
Imports System.Configuration
Imports System.Xml
Imports System.IO
Namespace elGuille.info.Util
Public Class ConfigXml
'----------------------------------------------------------------------
' Los campos y métodos privados
'----------------------------------------------------------------------
Private mGuardarAlAsignar As Boolean = True
Private Const configuration As String = "configuration/"
Private ficConfig As String = ""
Private configXml As New XmlDocument
'
''' <summary>
''' Indica si se se guardarán los datos cuando se añadan nuevos.
''' </summary>
Public Property GuardarAlAsignar() As Boolean
Get
Return mGuardarAlAsignar
End Get
Set(ByVal value As Boolean)
mGuardarAlAsignar = value
End Set
End Property
'
''' <summary>
''' Obtiene un valor de tipo cadena de la sección y clave indicadas.
''' </summary>
Public Function GetValue(ByVal seccion As String, ByVal clave As String) As String
Return GetValue(seccion, clave, "")
End Function
''' <summary>
''' Obtiene un valor de tipo cadena de la sección y clave indicadas.
''' </summary>
Public Function GetValue(ByVal seccion As String, _
ByVal clave As String, _
ByVal predeterminado As String) As String
Return cfgGetValue(seccion, clave, predeterminado)
End Function
''' <summary>
''' Obtiene un valor de tipo entero de la sección y clave indicadas.
''' </summary>
Public Function GetValue(ByVal seccion As String, _
ByVal clave As String, _
ByVal predeterminado As Integer) As Integer
Return CInt(cfgGetValue(seccion, clave, predeterminado.ToString))
End Function
''' <summary>
''' Obtiene un valor de tipo boolean de la sección y clave indicadas.
''' </summary>
Public Function GetValue(ByVal seccion As String, _
ByVal clave As String, _
ByVal predeterminado As Boolean) As Boolean
Dim def As String = "0"
If predeterminado Then def = "1"
def = cfgGetValue(seccion, clave, def)
If def = "1" Then
Return True
Else
Return False
End If
End Function
''' <summary>
''' Asignar un valor de tipo cadena en la sección y clave indicadas.
''' </summary>
Public Sub SetValue(ByVal seccion As String, _
ByVal clave As String, ByVal valor As String)
cfgSetValue(seccion, clave, valor)
End Sub
''' <summary>
''' Asignar un valor de tipo entero en la sección y clave indicadas.
''' </summary>
Public Sub SetValue(ByVal seccion As String, _
ByVal clave As String, ByVal valor As Integer)
cfgSetValue(seccion, clave, valor.ToString)
End Sub
''' <summary>
''' Asignar un valor de tipo boolean en la sección y clave indicadas.
''' </summary>
Public Sub SetValue(ByVal seccion As String, _
ByVal clave As String, ByVal valor As Boolean)
If valor Then
cfgSetValue(seccion, clave, "1")
Else
cfgSetValue(seccion, clave, "0")
End If
End Sub
''' <summary>
''' Asigna un valor de tipo cadena en la sección y clave indicadas.
''' </summary>
Public Sub SetKeyValue(ByVal seccion As String, _
ByVal clave As String, ByVal valor As String)
cfgSetKeyValue(seccion, clave, valor)
End Sub
''' <summary>
''' Asigna un valor de tipo entero en la sección y clave indicadas.
''' </summary>
Public Sub SetKeyValue(ByVal seccion As String, _
ByVal clave As String, ByVal valor As Integer)
cfgSetKeyValue(seccion, clave, valor.ToString)
End Sub
''' <summary>
''' Asigna un valor de tipo boolean en la sección y clave indicadas.
''' </summary>
Public Sub SetKeyValue(ByVal seccion As String, _
ByVal clave As String, ByVal valor As Boolean)
If valor Then
cfgSetKeyValue(seccion, clave, "1")
Else
cfgSetKeyValue(seccion, clave, "0")
End If
End Sub
''' <summary>
''' Elimina la sección indicada, aunque en realidad la deja vacía.
''' </summary>
Public Sub RemoveSection(ByVal seccion As String)
Dim n As XmlNode
n = configXml.SelectSingleNode(configuration & seccion)
If Not n Is Nothing Then
n.RemoveAll()
If mGuardarAlAsignar Then
Me.Save()
End If
End If
End Sub
' Guardar el fichero de configuración
'
''' <summary>
''' Guardar el fichero de configuración.
''' </summary>
Public Sub Save()
configXml.Save(ficConfig)
End Sub
''' <summary>
''' Lee el fichero de configuración.
''' </summary>
Public Sub Read()
Dim fic As String = ficConfig
Const revDate As String = "Thu, 17 Aug 2006 20:20:00 GMT"
If File.Exists(fic) Then
configXml.Load(fic)
' Actualizar los datos de la información de esta clase
Dim b As Boolean = mGuardarAlAsignar
mGuardarAlAsignar = False
Me.SetValue("configXml_Info", "info", _
"Generado con Config para Visual Basic 2003")
Me.SetValue("configXml_Info", "revision", revDate)
Me.SetValue("configXml_Info", "formatoUTF8", _
"El formato de este fichero debe ser UTF-8")
mGuardarAlAsignar = b
Me.Save()
Else
' Crear el XML de configuración con la sección General
Dim sb As New System.Text.StringBuilder
sb.Append("<?xml version=""1.0"" encoding=""utf-8"" ?>")
sb.Append("<configuration>")
' Por si es un fichero appSetting
sb.Append("<configSections>")
sb.Append("<section name=""General"" " & _
"type=""System.Configuration.DictionarySectionHandler"" />")
sb.Append("</configSections>")
sb.Append("<General>")
sb.Append("<!-- Los valores irán dentro del elemento indicado por la clave -->")
sb.Append("<!-- Aunque también se podrán indicar como pares key / value -->")
sb.AppendFormat("<add key=""Revisión"" value=""{0}"" />", revDate)
sb.Append("<!-- La clase siempre los añade como un elemento -->")
sb.Append("<Copyright>©Guillermo 'guille' Som, 2005-2006</Copyright>")
sb.Append("</General>")
'
sb.AppendFormat("<configXml_Info>{0}", vbCrLf)
sb.AppendFormat("<info>Generado con Config para Visual Basic 2003</info>{0}", _
vbCrLf)
sb.AppendFormat("<copyright>©Guillermo 'guille' Som, 2005-2006" & _
"</copyright>{0}", _
vbCrLf)
sb.AppendFormat("<revision>{0}</revision>{1}", revDate, vbCrLf)
sb.AppendFormat("<formatoUTF8>El formato de este fichero debe ser UTF-8" & _
"</formatoUTF8>{0}", _
vbCrLf)
sb.AppendFormat("</configXml_Info>{0}", vbCrLf)
'
sb.Append("</configuration>")
' Asignamos la cadena al objeto
configXml.LoadXml(sb.ToString)
'
' Guardamos el contenido de configXml y creamos el fichero
configXml.Save(ficConfig)
End If
End Sub
''' <summary>
''' El nombre del fichero de configuración.
''' </summary>
Public Property FileName() As String
Get
Return ficConfig
End Get
Set(ByVal value As String)
' Al asignarlo, NO leemos el contenido del fichero
ficConfig = value
'LeerFile()
End Set
End Property
''' <summary>
''' Constructor en el que indicamos el nombre del fichero de configuración.
''' </summary>
Public Sub New(ByVal fic As String)
ficConfig = fic
' Por defecto se guarda al asignar los valores
mGuardarAlAsignar = True
Read()
End Sub
' Con este constructor podemos decidir si guardamos o no automáticamente
''' <summary>
''' Constructor en el que indicamos el nombre del fichero de configuración.
''' </summary>
Public Sub New(ByVal fic As String, ByVal guardarAlAsignar As Boolean)
ficConfig = fic
mGuardarAlAsignar = guardarAlAsignar
Read()
End Sub
'
''' <summary>
''' Devuelve una colección de tipo StringCollection
''' con las secciones del fichero de configuración.
''' </summary>
Public Function Secciones() As StringCollection
Dim d As New StringCollection
Dim root As XmlNode
Dim s As String = "configuration"
root = configXml.SelectSingleNode(s)
If Not root Is Nothing Then
For Each n As XmlNode In root.ChildNodes
d.Add(n.Name)
Next
End If
Return d
End Function
''' <summary>
''' Devuelve una colección de tipo StringDictionary
''' con las claves y valores de la sección indicada.
''' </summary>
Public Function Claves(ByVal seccion As String) As StringDictionary
Dim d As New StringDictionary
Dim root As XmlNode
seccion = seccion.Replace(" ", "_")
root = configXml.SelectSingleNode(configuration & seccion)
If Not root Is Nothing Then
For Each n As XmlNode In root.ChildNodes
If d.ContainsKey(n.Name) = False Then
d.Add(n.Name, n.InnerText)
End If
Next
End If
Return d
End Function
'
'----------------------------------------------------------------------
' Los métodos privados
'----------------------------------------------------------------------
'
' El método interno para guardar los valores
' Este método siempre guardará en el formato:
' <seccion><clave>valor</clave></seccion>
Private Sub cfgSetValue( _
ByVal seccion As String, _
ByVal clave As String, _
ByVal valor As String)
'
Dim n As XmlNode
'
' Filtrar los caracteres no válidos
' en principio solo comprobamos el espacio
seccion = seccion.Replace(" ", "_")
clave = clave.Replace(" ", "_")
' Se comprueba si es un elemento de la sección:
' <seccion><clave>valor</clave></seccion>
n = configXml.SelectSingleNode(configuration & seccion & "/" & clave)
If Not n Is Nothing Then
n.InnerText = valor
Else
Dim root As XmlNode
Dim elem As XmlElement
root = configXml.SelectSingleNode(configuration & seccion)
If root Is Nothing Then
' Si no existe el elemento principal,
' lo añadimos a <configuration>
elem = configXml.CreateElement(seccion)
configXml.DocumentElement.AppendChild(elem)
root = configXml.SelectSingleNode(configuration & seccion)
End If
If Not root Is Nothing Then
' Crear el elemento
elem = configXml.CreateElement(clave)
elem.InnerText = valor
' Añadirlo al nodo indicado
root.AppendChild(elem)
End If
End If
'
If mGuardarAlAsignar Then
Me.Save()
End If
End Sub
' Asigna un atributo a una sección
' Por ejemplo: <Seccion clave=valor>...</Seccion>
' También se usará para el formato de appSettings: <add key=clave value=valor />
' Aunque en este caso, debe existir el elemento a asignar.
Private Sub cfgSetKeyValue( _
ByVal seccion As String, _
ByVal clave As String, _
ByVal valor As String)
'
Dim n As XmlNode
'
' Filtrar los caracteres no válidos
' en principio solo comprobamos el espacio
seccion = seccion.Replace(" ", "_")
clave = clave.Replace(" ", "_")
n = configXml.SelectSingleNode(configuration & seccion & _
"/add[@key=""" & clave & """]")
If Not n Is Nothing Then
n.Attributes("value").InnerText = valor
Else
Dim root As XmlNode
Dim elem As XmlElement
root = configXml.SelectSingleNode(configuration & seccion)
If root Is Nothing Then
' Si no existe el elemento principal,
' lo añadimos a <configuration>
elem = configXml.CreateElement(seccion)
configXml.DocumentElement.AppendChild(elem)
root = configXml.SelectSingleNode(configuration & seccion)
End If
If Not root Is Nothing Then
Dim a As XmlAttribute = CType( _
configXml.CreateNode(XmlNodeType.Attribute, _
clave, Nothing), _
XmlAttribute)
a.InnerText = valor
root.Attributes.Append(a)
End If
End If
If mGuardarAlAsignar Then
Me.Save()
End If
End Sub
' Devolver el valor de la clave indicada
Private Function cfgGetValue( _
ByVal seccion As String, _
ByVal clave As String, _
ByVal valor As String _
) As String
'
Dim n As XmlNode
'
' Filtrar los caracteres no válidos
' en principio solo comprobamos el espacio
seccion = seccion.Replace(" ", "_")
clave = clave.Replace(" ", "_")
' Primero comprobar si están el formato de appSettings:
' <add key = clave value = valor />
n = configXml.SelectSingleNode(configuration & _
seccion & "/add[@key=""" & clave & """]")
If Not n Is Nothing Then
Return n.Attributes("value").InnerText
End If
'
' Después se comprueba si está en el formato <Seccion clave = valor>
n = configXml.SelectSingleNode(configuration & seccion)
If Not n Is Nothing Then
Dim a As XmlAttribute = n.Attributes(clave)
If Not a Is Nothing Then
Return a.InnerText
End If
End If
'
' Por último se comprueba si es un elemento de seccion:
' <seccion><clave>valor</clave></seccion>
n = configXml.SelectSingleNode(configuration & seccion & "/" & clave)
If Not n Is Nothing Then
Return n.InnerText
End If
'
' Si no existe, se devuelve el valor predeterminado
Return valor
End Function
End Class
End Namespace
|
El código para C#
(cualquier versión)
|
//-----------------------------------------------------------------------------
// Clase para manejar ficheros de configuración (17/Ago/06)
//
// Versión para Visual C# 2003 basada en la clase de Visual Basic .NET 2003
//
// Las secciones siempre estarán dentro de <configuration> y </configuration>
//
// ©Guillermo 'guille' Som, 2005-2006
//-----------------------------------------------------------------------------
using System;
using System.Collections;
using System.Collections.Specialized;
using System.Configuration;
using System.Xml;
using System.IO;
namespace elGuille.info.Util
{
public class ConfigXml
{
//----------------------------------------------------------------------
// Los campos y métodos privados
//----------------------------------------------------------------------
private bool mGuardarAlAsignar = true;
const string configuration = "configuration/";
private string ficConfig = "";
private XmlDocument configXml = new XmlDocument();
//
/// <summary>
/// Indica si se se guardarán los datos cuando se añadan nuevos.
/// </summary>
/// <value>
/// Indica si se se guardarán los datos cuando se añadan nuevos.
/// </value>
/// <returns>
/// Un valor verdadero o falso según el valor de la propiedad
/// </returns>
public bool GuardarAlAsignar
{
get
{
return mGuardarAlAsignar;
}
set
{
mGuardarAlAsignar = value;
}
}
//
/// <summary>
/// Obtiene un valor de tipo cadena de la sección y clave indicadas.
/// </summary>
/// <param name="seccion">La sección de la que queremos obtener el valor
/// </param>
/// <param name="clave">La clave de la que queremos recuperar el valor
/// </param>
/// <returns>
/// Un valor de tipo cadena con el valor de la sección y clave indicadas
/// </returns>
/// <remarks>
/// Existe otra sobrecarga para indicar un valor predeterminado.
/// Tanbién hay otras dos sobrecargas para valores enteros y boolean.
/// </remarks>
public string GetValue(string seccion, string clave)
{
return GetValue(seccion, clave, "");
}
/// <summary>
/// Obtiene un valor de tipo cadena de la sección y clave indicadas.
/// </summary>
/// <param name="seccion">La sección de la que queremos obtener el valor
/// </param>
/// <param name="clave">La clave de la que queremos recuperar el valor
/// </param>
/// <param name="predeterminado">
/// El valor predeterminado para cuando no exista.
/// </param>
/// <returns>
/// Un valor de tipo cadena con el valor de la sección y clave indicadas
/// </returns>
public string GetValue(string seccion, string clave, string predeterminado)
{
return cfgGetValue(seccion, clave, predeterminado);
}
/// <summary>
/// Obtiene un valor de tipo entero de la sección y clave indicadas.
/// </summary>
/// <param name="seccion">La sección de la que queremos obtener el valor
/// </param>
/// <param name="clave">La clave de la que queremos recuperar el valor
/// </param>
/// <param name="predeterminado">
/// El valor predeterminado para cuando no exista.
/// </param>
/// <returns>
/// Un valor de tipo entero con el valor de la sección y clave indicadas
/// </returns>
public int GetValue(string seccion, string clave, int predeterminado)
{
return Convert.ToInt32(cfgGetValue(seccion, clave, predeterminado.ToString()));
}
/// <summary>
/// Obtiene un valor de tipo boolean de la sección y clave indicadas.
/// </summary>
/// <param name="seccion">La sección de la que queremos obtener el valor
/// </param>
/// <param name="clave">La clave de la que queremos recuperar el valor
/// </param>
/// <param name="predeterminado">
/// El valor predeterminado para cuando no exista.
/// </param>
/// <returns>
/// Un valor de tipo boolean con el valor de la sección y clave indicadas
/// </returns>
/// <remarks>
/// Internamente el valor se guarda con un cero para False y uno para True
/// </remarks>
public bool GetValue(string seccion, string clave, bool predeterminado)
{
string def = "0";
if( predeterminado ) def = "1";
def = cfgGetValue(seccion, clave, def);
if( def == "1" )
{
return true;
}
else
{
return false;
}
}
/// <summary>
/// Asignar un valor de tipo cadena en la sección y clave indicadas.
/// </summary>
/// <param name="seccion">La sección de la que queremos obtener el valor
/// </param>
/// <param name="clave">La clave de la que queremos recuperar el valor
/// </param>
/// <param name="valor">El valor a asignar</param>
/// <remarks>
/// El valor se guardar como un elemento de la sección indicada.
/// <seealso cref="SetKeyValue" />
/// </remarks>
public void SetValue(string seccion, string clave, string valor)
{
cfgSetValue(seccion, clave, valor);
}
/// <summary>
/// Asignar un valor de tipo entero en la sección y clave indicadas.
/// </summary>
/// <param name="seccion">La sección de la que queremos obtener el valor
/// </param>
/// <param name="clave">La clave de la que queremos recuperar el valor
/// </param>
/// <param name="valor">El valor a asignar</param>
/// <remarks>
/// El valor se guardar como un elemento de la sección indicada.
/// El valor siempre se guarda como un valor de cadena.
/// <seealso cref="SetKeyValue" />
/// </remarks>
public void SetValue(string seccion, string clave, int valor)
{
cfgSetValue(seccion, clave, valor.ToString());
}
/// <summary>
/// Asignar un valor de tipo boolean en la sección y clave indicadas.
/// </summary>
/// <param name="seccion">La sección de la que queremos obtener el valor
/// </param>
/// <param name="clave">La clave de la que queremos recuperar el valor
/// </param>
/// <param name="valor">El valor a asignar</param>
/// <remarks>
/// El valor se guardar como un elemento de la sección indicada.
/// El valor siempre se guarda como un valor de cadena,
/// siendo un 1 para True y 0 para False.
/// <seealso cref="SetKeyValue" />
/// </remarks>
public void SetValue(string seccion, string clave, bool valor)
{
if( valor )
{
cfgSetValue(seccion, clave, "1");
}
else
{
cfgSetValue(seccion, clave, "0");
}
}
/// <summary>
/// Asigna un valor de tipo cadena en la sección y clave indicadas.
/// </summary>
/// <param name="seccion">La sección de la que queremos obtener el valor
/// </param>
/// <param name="clave">La clave de la que queremos recuperar el valor
/// </param>
/// <param name="valor">El valor a asignar</param>
/// <remarks>
/// El valor se guarda como un atributo de la sección indicada.
/// La clave se guarda con el atributo key y el valor con el atributo value.
/// <seealso cref="SetValue" />
/// </remarks>
public void SetKeyValue(string seccion, string clave, string valor)
{
cfgSetKeyValue(seccion, clave, valor);
}
/// <summary>
/// Asigna un valor de tipo entero en la sección y clave indicadas.
/// </summary>
/// <param name="seccion">La sección de la que queremos obtener el valor
/// </param>
/// <param name="clave">La clave de la que queremos recuperar el valor
/// </param>
/// <param name="valor">El valor a asignar</param>
/// <remarks>
/// El valor se guarda como un atributo de la sección indicada.
/// La clave se guarda con el atributo key y el valor con el atributo value.
/// El valor siempre se guarda como un valor de cadena.
/// <seealso cref="SetValue" />
/// </remarks>
public void SetKeyValue(string seccion, string clave, int valor)
{
cfgSetKeyValue(seccion, clave, valor.ToString());
}
/// <summary>
/// Asigna un valor de tipo boolean en la sección y clave indicadas.
/// </summary>
/// <param name="seccion">La sección de la que queremos obtener el valor
/// </param>
/// <param name="clave">La clave de la que queremos recuperar el valor
/// </param>
/// <param name="valor">El valor a asignar</param>
/// <remarks>
/// El valor se guarda como un atributo de la sección indicada.
/// La clave se guarda con el atributo key y el valor con el atributo value.
/// El valor siempre se guarda como un valor de cadena,
/// siendo un 1 para True y 0 para False.
/// <seealso cref="SetValue" />
/// </remarks>
public void SetKeyValue(string seccion, string clave, bool valor)
{
if( valor )
{
cfgSetKeyValue(seccion, clave, "1");
}
else
{
cfgSetKeyValue(seccion, clave, "0");
}
}
/// <summary>
/// Elimina la sección indicada, aunque en realidad la deja vacía.
/// </summary>
/// <param name="seccion">La sección a eliminar.</param>
public void RemoveSection(string seccion)
{
XmlNode n;
n = configXml.SelectSingleNode(configuration + seccion);
if( n != null )
{
n.RemoveAll();
if( mGuardarAlAsignar )
{
this.Save();
}
}
}
/// <summary>
/// Guardar el fichero de configuración.
/// </summary>
/// <remarks>
/// Si no se llama a este método, no se guardará de forma permanente.
/// Para guardar automáticamente al asignar,
/// asignar un valor verdadero a la propiedad
/// <see cref="GuardarAlAsignar">GuardarAlAsignar</see>
/// </remarks>
public void Save()
{
configXml.Save(ficConfig);
}
/// <summary>
/// Lee el fichero de configuración.
/// </summary>
/// <remarks>
/// Si no existe, se crea uno nuevo con los valores predeterminados.
/// </remarks>
public void Read()
{
string fic = ficConfig;
const string revDate = "Thu, 17 Aug 2006 20:20:00 GMT";
if( File.Exists(fic) )
{
configXml.Load(fic);
// Actualizar los datos de la información de esta clase
bool b = mGuardarAlAsignar;
mGuardarAlAsignar = false;
this.SetValue("configXml_Info", "info",
"Generado con ConfigXml para Visual C# 2003");
this.SetValue("configXml_Info", "revision", revDate);
this.SetValue("configXml_Info", "formatoUTF8",
"El formato de este fichero debe ser UTF-8");
mGuardarAlAsignar = b;
this.Save();
}
else
{
// Crear el XML de configuración con la sección General
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.Append("<?xml version=\"1.0\" encoding=\"utf-8\" ?>");
sb.Append("<configuration>");
// Por si es un fichero appSetting
sb.Append("<configSections>");
sb.Append("<section name=\"General\" " +
"type=\"System.Configuration.DictionarySectionHandler\" />");
sb.Append("</configSections>");
sb.Append("<General>");
sb.Append("<!-- Los valores irán dentro del elemento indicado por la clave -->");
sb.Append("<!-- Aunque también se podrán indicar como pares key / value -->");
sb.AppendFormat("<add key=\"Revisión\" value=\"{0}\" />", revDate);
sb.Append("<!-- La clase siempre los añade como un elemento -->");
sb.Append("<Copyright>©Guillermo 'guille' Som, 2005-2006</Copyright>");
sb.Append("</General>");
//
sb.AppendFormat("<configXml_Info>{0}", "\r\n");
sb.AppendFormat("<info>Generado con Config para Visual C# 2003" +
"</info>{0}", "\r\n");
sb.AppendFormat("<copyright>©Guillermo 'guille' Som, 2005-2006" +
"</copyright>{0}", "\r\n");
sb.AppendFormat("<revision>{0}</revision>{1}", revDate, "\r\n");
sb.AppendFormat("<formatoUTF8>El formato de este fichero debe ser UTF-8" +
"</formatoUTF8>{0}", "\r\n");
sb.AppendFormat("</configXml_Info>{0}", "\r\n");
//
sb.Append("</configuration>");
// Asignamos la cadena al objeto
configXml.LoadXml(sb.ToString());
//
// Guardamos el contenido de configXml y creamos el fichero
configXml.Save(ficConfig);
}
}
/// <summary>
/// El nombre del fichero de configuración.
/// </summary>
/// <value>
/// El path completo con el nombre del fichero de configuración.
/// </value>
/// <returns>
/// Una cadena con el fichero de configuración.
/// </returns>
/// <remarks>
/// El nombre del fichero se debe indicar en el constructor.
/// La dejo como de escritura por si cambiamos el nombre
/// y usamos el método Save, se guardarán los datos en el nuevo fichero.
/// </remarks>
public string FileName
{
get
{
return ficConfig;
}
set
{
// Al asignarlo, NO leemos el contenido del fichero
ficConfig = value;
//LeerFile()
}
}
/// <summary>
/// Constructor en el que indicamos el nombre del fichero de configuración.
/// </summary>
/// <param name="fic">
/// El fichero a usar para guardar los datos de configuración.
/// </param>
/// <remarks>
/// Si no existe, se creará.
/// Al usar este constructor, por defecto se guardarán los valores al asignarlos.
/// </remarks>
public ConfigXml(string fic)
{
ficConfig = fic;
// Por defecto se guarda al asignar los valores
mGuardarAlAsignar = true;
Read();
}
// Con este constructor podemos decidir si guardamos o no automáticamente
/// <summary>
/// Constructor en el que indicamos el nombre del fichero de configuración.
/// </summary>
/// <param name="fic">
/// El fichero a usar para guardar los datos de configuración.
/// </param>
/// <param name="guardarAlAsignar">
/// Un valor verdadero o falso para indicar
/// si se guardan los datos automáticamente al asignarlos.
/// </param>
public ConfigXml(string fic, bool guardarAlAsignar)
{
ficConfig = fic;
mGuardarAlAsignar = guardarAlAsignar;
Read();
}
//
/// <summary>
/// Devuelve una colección de tipo StringCollection
/// con las secciones del fichero de configuración.
/// </summary>
/// <returns>
/// Una colección de tipo StringCollection
/// con las secciones del fichero de configuración.
/// </returns>
public StringCollection Secciones()
{
StringCollection d = new StringCollection();
XmlNode root;
string s = "configuration";
root = configXml.SelectSingleNode(s);
if( root != null )
{
foreach(XmlNode n in root.ChildNodes)
{
d.Add(n.Name);
}
}
return d;
}
/// <summary>
/// Devuelve una colección de tipo StringDictionary
/// con las claves y valores de la sección indicada.
/// </summary>
/// <param name="seccion">
/// La sección de la que queremos obtener las claves y valores.
/// </param>
/// <returns>
/// Una colección de tipo StringDictionary con las claves y valores.
/// </returns>
public StringDictionary Claves(string seccion)
{
StringDictionary d = new StringDictionary();
XmlNode root;
seccion = seccion.Replace(" ", "_");
root = configXml.SelectSingleNode(configuration + seccion);
if( root != null )
{
foreach(XmlNode n in root.ChildNodes)
{
if( d.ContainsKey(n.Name) == false )
{
d.Add(n.Name, n.InnerText);
}
}
}
return d;
}
//
//----------------------------------------------------------------------
// Los métodos privados
//----------------------------------------------------------------------
//
// El método interno para guardar los valores
// Este método siempre guardará en el formato:
// <seccion><clave>valor</clave></seccion>
private void cfgSetValue(string seccion, string clave, string valor)
{
//
XmlNode n;
//
// Filtrar los caracteres no válidos
// en principio solo comprobamos el espacio
seccion = seccion.Replace(" ", "_");
clave = clave.Replace(" ", "_");
// Se comprueba si es un elemento de la sección:
// <seccion><clave>valor</clave></seccion>
n = configXml.SelectSingleNode(configuration + seccion + "/" + clave);
if( n != null )
{
n.InnerText = valor;
}
else
{
XmlNode root;
XmlElement elem;
root = configXml.SelectSingleNode(configuration + seccion);
if( root == null )
{
// Si no existe el elemento principal,
// lo añadimos a <configuration>
elem = configXml.CreateElement(seccion);
configXml.DocumentElement.AppendChild(elem);
root = configXml.SelectSingleNode(configuration + seccion);
}
if( root != null )
{
// Crear el elemento
elem = configXml.CreateElement(clave);
elem.InnerText = valor;
// Añadirlo al nodo indicado
root.AppendChild(elem);
}
}
//
if( mGuardarAlAsignar )
{
this.Save();
}
}
// Asigna un atributo a una sección
// Por ejemplo: <Seccion clave=valor>...</Seccion>
// También se usará para el formato de appSettings:
// <add key=clave value=valor />
// Aunque en este caso, debe existir el elemento a asignar.
private void cfgSetKeyValue(string seccion, string clave, string valor)
{
//
XmlNode n;
//
// Filtrar los caracteres no válidos
// en principio solo comprobamos el espacio
seccion = seccion.Replace(" ", "_");
clave = clave.Replace(" ", "_");
n = configXml.SelectSingleNode(configuration + seccion + "/add[@key=\"" + clave + "\"]");
if( n != null )
{
n.Attributes["value"].InnerText = valor;
}
else
{
XmlNode root;
XmlElement elem;
root = configXml.SelectSingleNode(configuration + seccion);
if( root == null )
{
// Si no existe el elemento principal,
// lo añadimos a <configuration>
elem = configXml.CreateElement(seccion);
configXml.DocumentElement.AppendChild(elem);
root = configXml.SelectSingleNode(configuration + seccion);
}
if( root != null )
{
XmlAttribute a;
a = ((XmlAttribute)configXml.CreateNode(XmlNodeType.Attribute, clave, null));
a.InnerText = valor;
root.Attributes.Append(a);
}
}
if( mGuardarAlAsignar )
{
this.Save();
}
}
// Devolver el valor de la clave indicada
private string cfgGetValue(string seccion, string clave, string valor)
{
//
XmlNode n;
//
// Filtrar los caracteres no válidos
// en principio solo comprobamos el espacio
seccion = seccion.Replace(" ", "_");
clave = clave.Replace(" ", "_");
// Primero comprobar si están el formato de appSettings:
// <add key = clave value = valor />
n = configXml.SelectSingleNode(configuration + seccion + "/add[@key=\"" + clave + "\"]");
if( n != null )
{
return n.Attributes["value"].InnerText;
}
//
// Después se comprueba si está en el formato <Seccion clave = valor>
n = configXml.SelectSingleNode(configuration + seccion);
if( n != null )
{
XmlAttribute a = n.Attributes[clave];
if( a != null )
{
return a.InnerText;
}
}
//
// Por último se comprueba si es un elemento de seccion:
// <seccion><clave>valor</clave></seccion>
n = configXml.SelectSingleNode(configuration + seccion + "/" + clave);
if( n != null )
{
return n.InnerText;
}
//
// Si no existe, se devuelve el valor predeterminado
return valor;
}
}
}
|
Espacios de nombres usados en el código de este artículo:
System.Collections.Specialiced
System.Xml
System.IO
|