jueves, 22 de septiembre de 2011

Crear archivo XML dinámico con C#

Hola, hoy público mi segunda entrada de este blog. En algunas circunstancias, nos encontramos con la necesidad de crear un archivo XML el cual necesitamos que la información que contiene interactué de forma dinámica con alguna aplicación que tengamos. En mi caso, yo tenía que guardar información en una aplicación que no se conecta a una base de datos. Mi solución fue crear un archivo XML pero la información que este contenida, cambiaba dinámicamente con el funcionamiento del sistema. a continuación muestro como realizar eso.


Primero y a manera de anexo tengo dos funciones que utilizo.


La primera solo crea una carpeta, si la creación es exitosa responde True, caso contrario responde False. Y además si la carpeta ya existe pues retorna True también.
public static bool CrearCarpetaXml(string Ruta)
        {
            bool Respuesta = false;
            try
            {
                if (Directory.Exists(Ruta))
                {
                    Respuesta = true;
                }
                else
                {
                    Directory.CreateDirectory(Ruta);
                    Respuesta = true;
                }
                return Respuesta;
            }
            catch (Exception ex)
            {
               //logger.Error("Error en CrearCarpetaXml, ClaseXml:" + ex.Message);
                return Respuesta;
               //No fue posible crear el directorio...
            }

        }
La segunda función solo evalúa la existencia de algún archivo según alguna ruta especifica.
 public static bool ArchivoExiste(string Ruta)
        {
            try
            {
                if (File.Exists(Ruta))
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            catch (Exception ex)
            {
                //logger.Error("Error en ArchivoExiste, ClaseXml:" + ex.Message);
                return false;
            }
        }

La siguiente función crea el archivo XML que necesitamos, es necesario definir la estructura según las necesidades. Para este ejercicio, vamos a crear un archivo XML que contenga algunas ventas que se hagan en alguna aplicación. Vamos a tener un nodo principal que se va a llamar "Transacciones", este nodo va a tener dos nodos hijos del mismo nivel que son, "RespuestaExitosa", "RespuestaFallida". No sobra decir que el archivo se va a actualizar según el tipo de respuesta obtenida.
private static bool CrearXmlTransacciones()
        {
            bool rta = false;

            try
            {
                XmlTextWriter EscribirRec = new XmlTextWriter("ArchivosXml/Transacciones.xml", System.Text.Encoding.UTF8);

                EscribirRec.Formatting = Formatting.Indented;
                EscribirRec.Indentation = 2;
                EscribirRec.WriteStartDocument(false);
                EscribirRec.WriteComment("Lista de Transacciones");

                EscribirRec.WriteStartElement("Transacciones");
                EscribirRec.WriteStartElement("Respuestas");

                EscribirRec.WriteStartElement("RespuestaExitosa");
                EscribirRec.WriteEndElement();

                EscribirRec.WriteStartElement("RespuestaFallida");
                EscribirRec.WriteEndElement();

                EscribirRec.WriteEndElement();
                EscribirRec.WriteEndElement();
                EscribirRec.WriteEndDocument();
                EscribirRec.Close();
                rta = true;
            }
            catch (Exception ex)
            {
                rta = false;
            }

            return rta;
        }
Ya creado el archivo con la estructura que necesitamos, viene lo interesante, como hacer para modificar el contenido justo donde lo necesitamos. Para esto creamos otra función la cual va a buscar el nodo donde queremos ingresar información. Este es el código de la función, posteriormente lo explico.
public static bool NodoTransacciones(string CodRespuesta, string MensajeRespuesta, string CodProceso,
            string Proveedor, string Producto, string NombreProducto, string Monto, string Usuario)
        {
            XmlDocument XmlDoc;
            XmlNode Raiz;
            XmlNode ident;
            bool rta = false;

            try
            {
                 XmlDoc = new XmlDocument();
                 XmlDoc.Load("ArchivosXml/Transacciones.xml");
                 Raiz = XmlDoc.DocumentElement;
               

                if (CodRespuesta == "Exitosa")
                {
                    ident = Raiz.FirstChild.FirstChild; // las transacciones quedarán en las exitosas
                }
                else
                {
                    ident = Raiz.FirstChild.FirstChild.NextSibling; // las transacciones quedarán en las fallidas
                }

                XmlElement NuevaTransaccion = XmlDoc.CreateElement("Transaccion"); //Como vamos a llamar el nuevo nodo
                NuevaTransaccion.InnerXml = "<Nombre></Nombre><CodRespuesta></CodRespuesta><MensajeRespuesta></MensajeRespuesta><CodProceso></CodProceso>" +
                    "<Proveedor></Proveedor><Producto></Producto><NombreProducto></NombreProducto><Monto></Monto><Usuario></Usuario>"; // Este es el contenido que va a tener el nuevo nodo

                NuevaTransaccion.AppendChild(XmlDoc.CreateWhitespace("\r\n"));
                NuevaTransaccion["Nombre"].InnerText = "transaccion de prueba";
                NuevaTransaccion["CodRespuesta"].InnerText = CodRespuesta;
                NuevaTransaccion["MensajeRespuesta"].InnerText = MensajeRespuesta;
                NuevaTransaccion["CodProceso"].InnerText = CodProceso;
                NuevaTransaccion["Proveedor"].InnerText = Proveedor;
                NuevaTransaccion["Producto"].InnerText = Producto;
                NuevaTransaccion["NombreProducto"].InnerText = NombreProducto;
                NuevaTransaccion["Monto"].InnerText = Monto;
                NuevaTransaccion["Usuario"].InnerText = Usuario;
               
                ident.InsertAfter(NuevaTransaccion, ident.LastChild);
                XmlTextWriter EscribirRec = new XmlTextWriter("ArchivosXml/Transacciones.xml", System.Text.Encoding.UTF8);
                XmlDoc.WriteTo(EscribirRec);
                EscribirRec.Close();
                rta = true;
            }
            catch (Exception ex)
            {
                rta = false;
                //logger.Error("Error en NodoTransacciones, ClaseXml:" + ex.Message);
            }
            return rta;
        }
Lo importante en esta rutina es ubicarnos en el nodo donde queremos ingresar nuevos nodos. Yo uso en este caso un objeto llamado Raiz para ubicarme como su nombre lo dice en el nodo raíz del documento XML. Y después según el resultado de la transacción me ubico en el nodo que quiero usando el objeto ident.


Las propiedades que usamos para ubicarnos en los nodos que queremos son :


FirstChild: Hace referencia al primer nodo hijo de donde nos ubiquemos. También es posible ubicarse en el último con LastChild. Y para ubicarnos en el siguiente usamos NextSibling, entonces si ponemos una instrucción como Raiz.FirstChild.NextSiblig, estamos hablando del segundo nodo hijo del elemento raíz que en este caso se llama Respuestas.


Creamos un objeto de tipo XMLElement de nombre NuevaTrasaccion y le especificamos lo que va a contener con la propiedad NuevaTransaccion.InnerText.


Por último vamos a ver de que manera vamos a insertar el nuevo nodo con la nueva información que tenemos. Si queremos que se inserten antes o después, de últimos o de primeros. Para esto usamos el objeto que teniamos antes ident y con la propiedad InsertAfter, o también IsertBefore. En los argumentos le decimos lo que vamos a insertar y le indicamos en donde (si fuera de primero iden.FirstChild, si fuera de último ident.LastChild). 


Aquí les muestro el Xml Inicial, cuando apenas se crea:



Esta imagen muestra el XML con la nueva información.



Les pongo un ejemplo de como llamo estas cuatro funciones para crear los anteriores archivos



int k = 0;
            while(k <= 3)
            {
                if (CrearCarpetaXml("ArchivosXml"))
                {
                    if (ArchivoExiste("ArchivosXml/Transacciones.xml"))
                    {
                        NodoTransacciones("Exitosa", "Transaccion Exitsoa", "123", "01", "05", "Atun", "1000", "JLopez");

                        NodoTransacciones("NoExitosa", "No hay saldo disponible", "123", "01", "05", "Atun", "1000", "JLopez");
                    }
                    else 
                    {
                        CrearXmlTransacciones();
                    }
                }
                else
                {
                    //no se creo la carpeta
                }

                k++;
            }
Esto es todo por el momento, espero que le sirva a alguien esto. intenté ser lo más claro posible. Cualquier duda o comentario adelante.

4 comentarios:

  1. Gracias. Me hubiera gustado que estuviera también algún ejemplo de leer el archivo

    ResponderEliminar
  2. Muchas gracias por la info tio, me fue muy util para despejar las dudas que tenia sobre el acceso y modificacion de un XML

    ResponderEliminar
  3. Muchas gracias por sus comentarios, he estado inactivo porque me encuentro en Londres aprendiendo ingles. Hasta pronto.

    ResponderEliminar
  4. buenos dias, soy nuevo en la creacion de xml's, y me marca un error en como tienes como en tu codigo
    XmlDoc = new XmlDocument(); XmlDoc.Load("ArchivosXml/Transacciones.xml");
    me marca que "Falta el elemento raíz."

    ResponderEliminar