viernes, 5 de diciembre de 2025

LINQ: consultando documentos XML

Como vimos en la entrega anterior LINQ nos permite realizar consultas de una base de datos o archivos XML.

Suponiendo que tenemos un documento XML (empleado.xml) con el siguiente contenido:

<?xml version="1.0" encoding="UTF-8"?>
<Empleados>
<Empleado> 
<Id>4392552</Id>
<Nombre>Horacio</Nombre>
<Apellidos>Gomez Torres</Apellidos>
<Correo>horacio.gomez.tor@infotec.com</Correo>
<Salario>25000.00</Salario>
<Departamento>202</Departamento>
</Empleado>

<Empleado>
<Id>4292856</Id>
<Nombre>Veronica</Nombre>
<Apellidos>Uribe Gomora</Apellidos>
<Correo>veronica.uribe.gom@infotec.com</Correo>
<Salario>30000.00</Salario>
<Departamento>204</Departamento>
</Empleado>


<Empleado>
<Id>4701330</Id>
<Nombre>Karla</Nombre>
<Apellidos>Perez Perez</Apellidos>
<Correo>karla.perez.per@infotec.com</Correo>
<Salario>28000.00</Salario>
<Departamento>200</Departamento>
</Empleado>

</Empleados>

Lo que sigue es la creación de un proyecto .NET que nos permita leer ese documento y hacer consultas:

1. Creamos un nuevo proyecto con dotnet:

$ dotnet new console -n DemoLinqXml
$ cd DemoLinqXml

El documento XML (empleados.xml) debe estar en la misma ruta del proyecto. Ahora abrimos el programa principal Program.cs y lo editamos:

using System;
using System.Linq;
using System.Xml.Linq;

class Program
{
    static void Main()
    {
        XDocument doc = XDocument.Load("empleados.xml");

        var empleados = doc.Root.Elements("Empleado");

        // Aquí vamos a incluir las consultas
    }
}

Podríamos obtener todos los datos (como un SELECT):

using System;
using System.Linq;
using System.Xml.Linq;

class Program
{
    static void Main()
    {

        try
        {
            XDocument doc = XDocument.Load("empleados.xml");
            var empleados = doc.Root.Elements("Empleado");

            if (empleados != null)
            {
                Console.WriteLine("\t Obtener todos los empleados:");
                var todos = empleados.Select(e => new
                {
                    Id = (int)e.Element("Id"),
                    Nombre = (string)e.Element("Nombre"),
                    Apellidos = (string)e.Element("Apellidos"),
                    Correo = (string)e.Element("Correo"),
                    Salario = (decimal)e.Element("Salario"),
                    Departamento = (int)e.Element("Departamento")
                });

                foreach (var emp in todos)
                {
                    Console.WriteLine($"ID: {emp.Id}");
                    Console.WriteLine($"Nombre: {emp.Nombre} {emp.Apellidos}");
                    Console.WriteLine($"Correo: {emp.Correo}");
                    Console.WriteLine($"Salario: {emp.Salario}");
                    Console.WriteLine($"Departamento: {emp.Departamento}");
                    Console.WriteLine("-------------------------");
                }                

            }
        }
        catch (FileNotFoundException ex)
        {
            Console.WriteLine("El archivo no existe: {0}", ex.Message);
        }

    }
}

Si queremos obtener solo nombre y correo:

using System;
using System.Linq;
using System.Xml.Linq;

class Program
{
    static void Main()
    {

        try
        {
            XDocument doc = XDocument.Load("empleados.xml");
            var empleados = doc.Root.Elements("Empleado");

            if (empleados != null)
            {
               
                
                Console.WriteLine("\t Obtener solo nombre y correo:");
                var contactos = empleados
                .Select(e => new
                {
                    Nombre = (string)e.Element("Nombre"),
                    Correo = (string)e.Element("Correo")
                });
                foreach (var contacto in contactos)
                {
                    Console.WriteLine($"{contacto.Nombre} : {contacto.Correo}");
                }

            }
        }
        catch (FileNotFoundException ex)
        {
            Console.WriteLine("El archivo no existe: {0}", ex.Message);
        }

    }
}

Obtener el empleado que gana más:

Console.WriteLine("\t Obtener el empleado que gana mas:");
var top = empleados.OrderByDescending(e => (decimal)e.Element("Salario")).First();
Console.WriteLine($"El mayor salario es: \n{top} ");

Obtener todos los empleados que ganen mas de $26000.00 (usando una sintaxis similar a SQL):

Console.WriteLine("\t Obtener todos los empleados que ganen mas de $26000.00:");
var query = from e in empleados
                            where (decimal)e.Element("Salario") > 26000
                            orderby (string)e.Element("Nombre")
                            select new
                            {
                                Nombre = (string)e.Element("Nombre"),
                                Salario = (decimal)e.Element("Salario")
                            };

foreach (var emp in query)
{
  Console.WriteLine($"{emp.Nombre} - {emp.Salario:C}");                
}

Obtener empleado del departamento 202:

Console.WriteLine("\t Obtener empleado del departamento 202:");
var depto202 = empleados.Where(e => (int)e.Element("Departamento") == 202);

foreach (var emp in depto202)
{
   Console.WriteLine($"ID: {(int)emp.Element("Id")}");
   Console.WriteLine($"Nombre: {(string)emp.Element("Nombre")}");
   Console.WriteLine($"Apellidos: {(string)emp.Element("Apellidos")}");
   Console.WriteLine($"Correo: {(string)emp.Element("Correo")}");
   Console.WriteLine($"Salario: {(decimal)emp.Element("Salario")}");
   Console.WriteLine($"Departamento: {(int)emp.Element("Departamento")}");
   Console.WriteLine("-------------------------");
}

Código completo:

using System;
using System.Linq;
using System.Xml.Linq;

class Program
{
    static void Main()
    {

        try
        {
            XDocument doc = XDocument.Load("empleados.xml");
            var empleados = doc.Root.Elements("Empleado");

            if (empleados != null)
            {
                Console.WriteLine("\t Obtener todos los empleados:");
                var todos = empleados.Select(e => new
                {
                    Id = (int)e.Element("Id"),
                    Nombre = (string)e.Element("Nombre"),
                    Apellidos = (string)e.Element("Apellidos"),
                    Correo = (string)e.Element("Correo"),
                    Salario = (decimal)e.Element("Salario"),
                    Departamento = (int)e.Element("Departamento")
                });

                foreach (var emp in todos)
                {
                    Console.WriteLine($"ID: {emp.Id}");
                    Console.WriteLine($"Nombre: {emp.Nombre} {emp.Apellidos}");
                    Console.WriteLine($"Correo: {emp.Correo}");
                    Console.WriteLine($"Salario: {emp.Salario}");
                    Console.WriteLine($"Departamento: {emp.Departamento}");
                    Console.WriteLine("-------------------------");
                }
                
                Console.WriteLine("\t Obtener solo nombre y correo:");
                var contactos = empleados
                .Select(e => new
                {
                    Nombre = (string)e.Element("Nombre"),
                    Correo = (string)e.Element("Correo")
                });
                foreach (var contacto in contactos)
                {
                    Console.WriteLine($"{contacto.Nombre} : {contacto.Correo}");
                }

                Console.WriteLine("\t Obtener el empleado que gana mas:");
                var top = empleados.OrderByDescending(e => (decimal)e.Element("Salario")).First();
                Console.WriteLine($"El mayor salario es: \n{top} ");

                Console.WriteLine("\t Obtener todos los empleados que ganen mas de $26000.00:");
                var query = from e in empleados
                            where (decimal)e.Element("Salario") > 26000
                            orderby (string)e.Element("Nombre")
                            select new
                            {
                                Nombre = (string)e.Element("Nombre"),
                                Salario = (decimal)e.Element("Salario")
                            };

                foreach (var emp in query)
                {
                    Console.WriteLine($"{emp.Nombre} - {emp.Salario:C}");
                }


                Console.WriteLine("\t Obtener empleado del departamento 202:");
                var depto202 = empleados.Where(e => (int)e.Element("Departamento") == 202);
                foreach (var emp in depto202)
                {
                    Console.WriteLine($"ID: {(int)emp.Element("Id")}");
                    Console.WriteLine($"Nombre: {(string)emp.Element("Nombre")}");
                    Console.WriteLine($"Apellidos: {(string)emp.Element("Apellidos")}");
                    Console.WriteLine($"Correo: {(string)emp.Element("Correo")}");
                    Console.WriteLine($"Salario: {(decimal)emp.Element("Salario")}");
                    Console.WriteLine($"Departamento: {(int)emp.Element("Departamento")}");
                    Console.WriteLine("-------------------------");
                }

            }
        }
        catch (FileNotFoundException ex)
        {
            Console.WriteLine("El archivo no existe: {0}", ex.Message);
        }

    }
}

Ejecutamos el código:

$ dotnet run

Salida:

         Obtener todos los empleados:
ID: 4392552
Nombre: Horacio Gomez Torres
Correo: horacio.gomez.tor@infotec.com
Salario: 25000.00
Departamento: 202
-------------------------
ID: 4292856
Nombre: Veronica Uribe Gomora
Correo: veronica.uribe.gom@infotec.com
Salario: 30000.00
Departamento: 204
-------------------------
ID: 4701330
Nombre: Karla Perez Perez
Correo: karla.perez.per@infotec.com
Salario: 28000.00
Departamento: 200
-------------------------
         Obtener solo nombre y correo:
Horacio : horacio.gomez.tor@infotec.com
Veronica : veronica.uribe.gom@infotec.com
Karla : karla.perez.per@infotec.com
         Obtener el empleado que gana mas:
El mayor salario es:
<Empleado>
  <Id>4292856</Id>
  <Nombre>Veronica</Nombre>
  <Apellidos>Uribe Gomora</Apellidos>
  <Correo>veronica.uribe.gom@infotec.com</Correo>
  <Salario>30000.00</Salario>
  <Departamento>204</Departamento>
</Empleado>
         Obtener todos los empleados que ganen mas de $26000.00:
Karla - $28,000.00
Veronica - $30,000.00
         Obtener empleado del departamento 202:
ID: 4392552
Nombre: Horacio
Apellidos: Gomez Torres
Correo: horacio.gomez.tor@infotec.com
Salario: 25000.00
Departamento: 202
-------------------------

Ventajas y desventajas de usar LINQ for XML

Aquí una pequeña tabla con las ventajas y desventajas del uso de LINQ para leer documentos XML.

Aspecto Ventajas Desventajas
Rendimiento Rápido para XML pequeños o medianos No apto para XML muy grandes (carga completa en memoria)
Legibilidad Sintaxis clara, declarativa y fácil de mantener Puede ser más verboso que XPath en consultas profundas
Tipado Conversión automática a tipos C# Puede lanzar excepciones si faltan nodos o tipos incorrectos
Flexibilidad Fácil de combinar con otras colecciones LINQ Menos eficiente para búsquedas complejas o profundas
Portabilidad Integrado y natural en .NET No es estándar fuera del ecosistema .NET

Seguiremos con esta serie sobre tecnología .NET y C#.

Enlaces:

https://codemonkeyjunior.blogspot.com/2025/11/linq-un-lenguaje-de-consulta-para-c.html
https://learn.microsoft.com/es-es/dotnet/standard/linq/linq-xml-overview

No hay comentarios:

Publicar un comentario

Claude Code: un nuevo enfoque de la programación por pares

Claude Code es una herramienta de inteligencia artificial creada por Anthropic que funciona directamente en la terminal. Sirve para acele...

Etiquetas

Archivo del blog