C# y XML

En los foros siempre veo preguntas referentes al manejo de XML con C#, manejo que va desde su creación, consulta y edición, es por esto que me decidí a crear este documento en el que relato como trabajar XML con C#.

Para el manejo de XML, desde el Framework 3.5 se tiene un Namespace muy útil, el XML.Linq, éste será el que nos permitirá trabajar libremente con nuestros XML. Para empezar usaremos su clase «Principal» (según yo) la XDocument, esta nos permite: crear, leer, modificar (entre otras cosas) nuestros archivos. En fin, si deseas más documentación en la web puedes encontrar toda la que necesites para iniciar, por ahora empecemos a programar.

Para este ejemplo crearé una pequeña estructura de datos que contendrá información de los empleados de una compañía, la aplicación es de tipo WinForms.

Al proyecto de WinForm le agregamos un botón (bt_crear_XML) y llamara a nuestro método crear_XML, así:

private void bt_crear_XML_Click(object sender, EventArgs e)
{
            crear_XML();
}
private void crear_XML()
{
            XDocument miXML = new XDocument(new XDeclaration("1.0", "utf-8", "yes"),
                new XElement("Empleados",

                new XElement("Empleado",
                new XAttribute("Id_Empleado", "321654"),
                new XElement("Nombre", "Miguel Suarez"),
                new XElement("Edad", "30")),

                new XElement("Empleado",
                new XAttribute("Id_Empleado", "123456"),
                new XElement("Nombre", "Maria Martinez"),
                new XElement("Edad", "27")),

                new XElement("Empleado",
                new XAttribute("Id_Empleado", "987654"),
                new XElement("Nombre", "Juan Gonzales"),
                new XElement("Edad", "25"))
                ));
            miXML.Save(@"C:\Prueba\MiDoc.xml""); //Debes tener permisos sobre la carpeta
            MessageBox.Show("Se ha creado un XML");
}

NOTA: No olvides agregar el namespace Xml.Linq (using System.Xml.Linq;)

Si ejecutas y pulsas el botón, vuala, habrás creado un XML. Como ves es bastante fácil, haciendo uso de las clases que nos proporciona este namespace. Perooo, ¿y ya? hasta aquí este post sería muy corto, así que me adelantaré y expondré un poco de Linq to Xml.

Consultar un Dato especifico

Para consultar un dato especifico, creare la función «buscarEnXml» que esperara un parámetro del tipo string (el Id_Empleado), la función queda así:

private void buscarEnXML(string idempleado)
{
            XDocument miXML = XDocument.Load(@"C:\Prueba\MiDoc.xml"); //Cargar el documento

            var nombreusu = from nombre in miXML.Elements("Empleados").Elements("Empleado")
                            where nombre.Attribute("Id_Empleado").Value == idempleado //Consultamos por el atributo
                            select nombre.Element("Nombre").Value; //Seleccionamos el nombre

            foreach (string minom in nombreusu)
            {
                MessageBox.Show(minom); //Mostramos un mensaje con el nombre del empleado que corresponde
            }
}

NOTA: para poder realizar consultas Linq, debes importar el namespace Linq (using System.Linq)

Cómo agregar un nuevo nodo.

Para agregar un nuevo nodo se usa la propiedad Root del XDocument, ésta propiedad obtiene la raiz del documento, dándonos la posibilidad de agregar los elementos y atributos de manera muy fácil, para esto, he creado un método addNode, que espera los parámetros id_Empleado, nombre y edad; todos del tipo string, el código queda así:

private void addNode(string idEmpleado, string nombre, string edad)
{
            XDocument miXML = XDocument.Load(@"C:\Prueba\MiDoc.xml"); //Cargamos
            miXML.Root.Add(   //Obtiene la raiz del documento (Empleados)                         
                new XElement("Empleado",
                    new XAttribute("Id_Empleado", idEmpleado),
                    new XElement("Nombre", nombre),
                    new XElement("Edad", edad))
                    );
            miXML.Save(@"C:\Prueba\MiDoc.xml");
}

Cómo eliminar un nodo

Para eliminar un nodo se debe consultar si este existe, luego si se dispone a eliminar elemento a elemento con un foreach, esta es la forma en que yo lo hago, no se si exista una mas optima, (si conoces alguna te agradecería me lo hicieras saber). Creé un método dropNode, que espera el parámetro IdEmpleado del tipo string, el método queda así:

private void dropNode(string idEmpleado)
{
            XDocument miXML = XDocument.Load(@"C:\Prueba\MiDoc.xml"); //Cargar el archivo           

            var consul = from persona in miXML.Elements("Empleados").Elements("Empleado")
                         where persona.Attribute("Id_Empleado").Value == idEmpleado
                         select persona;
            consul.ToList().ForEach(x => x.Remove()); //Remover elemento a elemento.
            miXML.Save(@"C:\Prueba\MiDoc.xml");            
}

Con este ultimo método hemos acabado con las operaciones básicas de acceso a datos, espero les halla sido de utilidad.

Descarga el ejemplo

Hasta el próximo post.

19 comentarios sobre “C# y XML

    1. Hola Isrrael, especificamente que post te gustaria ver?? cuaentame que necesitas y le saco un tiempo para hacer el post.

      Saludos. . .

  1. Ups, perdón por la tardanza…
    Bueno, especificamente:
    Tengo un archivo XML, en él necesito insertar un nuevo nodo, dicho nodo puede tener cualquier cosa dentro, pero necesito poder colocarle un namespace que NO necesariamente se declara en el nodo, sino puede necesitar declararse en el nodo raiz, además, dicho namespace debe incluirse en todos los nodos que se encuentren dentro del nodo insertado, donde puede haber cualquier numero de nodos hijos y profundidades de ellos, los cuales, son para mí «desconocidos».
    Está medio fumado esto, verdad?
    Saludos Compa

  2. Saludos, es muy interesante tu post, tengo una pregunta no se si me puedas hacer el favor de contestar.
    ¿Como puedo agregar un nodo dentro de otro nodo?

    1. Hola Alberto, esto que dices es muy facil, solo basta con definir un nuevo elemento con un nuevo atributo dentro del «nodo padre», modificando el metodo del ejemplo te quedaria así:

      XDocument miXML = XDocument.Load(@»C:\Prueba\MiDoc.xml»);
      miXML.Root.Add(
      new XElement(«Empleado»,
      new XAttribute(«Id_Empleado», idEmpleado),
      new XElement(«Hijos»,
      new XAttribute(«Id_Hijo»,»321654″),
      new XElement («NombreHijo», «Nicolocodev»),
      new XElement («ApellidoHijo», «Herrera»)),
      new XElement(«Nombre», nombre),
      new XElement(«Edad», edad))
      );

      miXML.Save(@»C:\Prueba\MiDoc.xml»);

      veras que alli agreago los datos de los hijos del empleado como un nuevo NODO,
      Gracias por la pregunta (esta muy buena), espero te sea de utilidad
      Saludos.

  3. Muchas gracias….me fue de mucha utilidad… estoy haciendo un proyecto y tambien me tope con otro problema, disculpa por molestar con tantas dudas….
    supongamis que tenemos el siguiente xml

    ¿Como puedo hacer para que con linq me regrese los los nodos hijo de root pero no los hijos de los hijos: osea el resultado sea nod1 y nod2 sin lo que contiene cada uno, espero me puedas responder y una vez mas disculpa si molesto :p

    1. Hola Alberto, mm sigue sin salir el XML, prueba pegandolo primero en un Notepad y luego si aqui.
      Ahora segun entiendo tu duda, deseas obtener todos los nodos Hijos de Root pero sin contener sus hijos. con Linq to Xml lo puedes hacer así:

      var nombreusu = from nombre in miXML.Elements(«Empleados»).Elements(«Empleado»)
      select nombre.FirstNode;

      Saludos y no te preocupes por preguntar, todas las dudas que tengas son bienvenidas.

  4. Hola muy interesante tu articulo fue de ayuda. pero tengo la siguiente inquietud. como hago para agregar nuevos nodos hijos. a nodos padres que no estan en la Raiz? he tratado de muchas maneras pero no lo he logrado hacer. si agrego los nodos a la raiz me funciona con el metodo que tu propones. pero para nodos padres que no estan en la Raiz no me funciona.

    1. Hola Lusvin, Nodos padres fuera de la raiz del documento?? mm… esto no pinta bien, los documentos XML siempre tienen un elemento raiz, en este es donde se agregan todos los padres y los hijos de los hijos de los hijos. Tener multiples RAICES seria como tener muchos documentos XML en un solo archivo. De hecho si miras un XML como el WebConfig o el app.condig, veras que todo se agrega dentro del elemento Raíz

      Saludos.

  5. SaludOS. Muy buen post, esta claro en cuanto a lo que explicas. buen trabajo

    Tengo un apregunta:

    Como puedo obtener el nombre del atributo?
    me explico
    cuando haces la consulta con linq, obtienes el valor de ese atributo, por ejemplo

    Id_Empleado=»juan perez»

    con tu consulta, obtienes «juan Perez»

    lo que yo necesito saber, es como obtener el nombre del atributo, en este caso id_empleado

    Un saludo

    1. Hola

      Antes de nada que pena por la tardanza, eh estado muy ocupado con el evento de ExpertDay, que de por cierto estuvo muy bueno 😀

      Para hacer lo que deseas si te entiendo bien, es recuperar una coleccion, pude ser de atributos o bien de elementos, te dejo el ejemplo de ambos para que rectifiques si es lo que deseas, mira:

      var atributos = miXML.Elements(«Empleados»).Elements(«Empleado»).Attributes();
      var elementos = miXML.Elements(«Empleados»).Elements(«Empleado»).Elements();
      string atributo = atributos.First().Name.LocalName;

  6. Amigo me encanto tu trabajo, excelente, muy bien. =)
    solo tengo una duda, se puedeutilizar para poocket pc windows mobil 5.0??

  7. Hola amigo, perdón por molestar de nuevo, ya implemente los métodos y me funcionan muy bien; Pero ahora tengo una duda, como puedo llamar a todos los nombres de todos los empleados para que los liste en un comboBox.
    saludos. y de ante mano muchas gracias =)

    1. Hola @Jorge, el código quedaría de la forma:

      XDocument miXML = XDocument.Load(@"C:\Prueba\MiDoc.xml");
      var empleados = miXML.Elements("Empleados")
      .Elements("Empleado")
      .Select(x => new
      {
      Nombre = x.Element("Nombre").Value,
      Id = x.Attribute("Id_Empleado")
      }).ToList();
      comboBox1.DisplayMember = "Nombre";
      comboBox1.ValueMember = "Id";
      comboBox1.DataSource = empleados;

Replica a Israel Marsilli Cancelar la respuesta