Continuamos con esta serie sobre LINQ y la lectura de archivos XML y JSON. Ahora profundizaremos un poco con las operaciones básicas que podemos realizar:
- Where: Filtrar.
- Select: Proyecta campos.
- OrderBy: Ordenar.
- GroupBy: Agrupar y contar.
- Join: Unir colecciones.
- Any: Comprobar existencia.
- All: Comprobar condición en todos.
- Count: Devolver cantidad.
Consultas en archivos XML con LINQ
Realizaremos algunas consultas teniendo como entrada el siguiente archivo XML:
empleados.xml
<?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> <Empleado> <Id>4701366</Id> <Nombre>Juan</Nombre> <Apellidos>Archundia Lara</Apellidos> <Correo>juan.archundia.lar@infotec.com</Correo> <Salario>38000.00</Salario> <Departamento>204</Departamento> </Empleado> </Empleados>
Mapearemos las etiquetas XML en una clase C#.
Empleado.cs
using System.Xml.Serialization; namespace model { public class Empleado { public string Id { get; set; } = string.Empty; public string Nombre { get; set; } = string.Empty; public string Apellidos { get; set; } = string.Empty; public string Correo { get; set; } = string.Empty; public decimal Salario { get; set; } = decimal.Zero; public string Departamento { get; set; } = string.Empty; } [XmlRoot("Empleados")] public class Empleados { [XmlElement("Empleado")] public List<Empleado> Lista { get; set; } } }
En una entrega anterior vimos cómo consultar documentos XML.
El siguiente bloque es importante para serializar los datos a partir de un documento XML.
// Ruta del archivo XML public static readonly string PATH_XML = "empleados.xml"; // Serializar datos var serializer = new XmlSerializer(typeof(Empleados)); // Lectura del XML using var reader = new StreamReader(PATH_XML);
Comenzaremos con la operación Where:
Console.WriteLine("Empleados mejor pagados:"); var empleadosBienPagados = from emp in empleados.Lista where emp.Salario > 28000 select emp; foreach (var emp in empleadosBienPagados) { Console.WriteLine($"{emp.Nombre} - {emp.Salario}"); }
En SQL sería:
SELECT * FROM empleados WHERE Salario > 28000;
Continuamos con la operación Select:
Console.WriteLine("Nombre y correo:"); var contactosDev = from dev in empleados.Lista select new { dev.Nombre, dev.Correo }; foreach (var emp in contactosDev) { Console.WriteLine($"{emp.Nombre} - {emp.Correo}"); }
En SQL sería:
SELECT Nombre, Correo FROM empleados;
Continuamos con la operación OrderBy:
Console.WriteLine("Empleados [por salario ascendente]:"); var empleadosOrdenados = from emp in empleados.Lista orderby emp.Salario select emp; foreach (var emp in empleadosOrdenados) { Console.WriteLine($"{emp.Nombre} {emp.Apellidos}, Depto: {emp.Departamento} , Salario: {emp.Salario}"); }
En SQL sería:
SELECT Nombre, Apellidos, Departamento, Salario FROM empleados ORDER BY Salario ASC;
Continuamos con la operación GroupBy y Count:
Console.WriteLine("Agrupar empleados por departamento:"); var empleadosPorDepto = from emp in empleados.Lista group emp by emp.Departamento into deptGroup select new { Departamento = deptGroup.Key, Cantidad = deptGroup.Count() }; foreach (var emp in empleadosPorDepto) { Console.WriteLine($"Departamento: {emp.Departamento} , Cantidad: {emp.Cantidad}"); }
En SQL sería:
SELECT Departamento, COUNT(*) AS Cantidad FROM empleados GROUP BY Departamento;
Para el conteo (COUNT) sería:
SELECT COUNT(*) AS TotalEmpleados FROM empleados;
Continuamos con la operación Any:
bool hayAltosSueldos = empleados.Lista.Any(e => e.Salario > 30000); if(hayAltosSueldos) { Console.WriteLine("Existe al menos un empleado con un salario relativamente grande."); }
En SQL sería:
SELECT CASE WHEN EXISTS (SELECT 1 FROM empleados WHERE Salario > 30000) THEN 'TRUE' ELSE 'FALSE' END AS HayAltosSueldos;
Finalizamos con la operación All:
bool todosConCorreoEdu = empleados.Lista.All(d => d.Correo.EndsWith("infotec.com")); if(todosConCorreoEdu) { Console.WriteLine("Todos los empleados tienen correo institucional."); }
En SQL sería:
SELECT CASE WHEN NOT EXISTS ( SELECT 1 FROM empleados WHERE Correo NOT LIKE '%infotec.com' ) THEN 'TRUE' ELSE 'FALSE' END AS TodosConCorreoInstitucional;
Programa completo:
Program.cs
using System; using System.IO; using System.Linq; using System.Collections.Generic; using System.Xml.Linq; using model; using System.Xml.Serialization; class Program { public static readonly string PATH_XML = "empleados.xml"; static void Main() { var serializer = new XmlSerializer(typeof(Empleados)); using var reader = new StreamReader(PATH_XML); Empleados empleados = (Empleados)serializer.Deserialize(reader); if(empleados != null) { Console.WriteLine("Empleados mejor pagados:"); var empleadosBienPagados = from emp in empleados.Lista where emp.Salario > 28000 select emp; foreach (var emp in empleadosBienPagados) { Console.WriteLine($"{emp.Nombre} - {emp.Salario}"); } Console.WriteLine("Nombre y correo:"); var contactosDev = from dev in empleados.Lista select new { dev.Nombre, dev.Correo }; foreach (var emp in contactosDev) { Console.WriteLine($"{emp.Nombre} - {emp.Correo}"); } Console.WriteLine("Empleados [por salario ascendente]:"); var empleadosOrdenados = from emp in empleados.Lista orderby emp.Salario select emp; foreach (var emp in empleadosOrdenados) { Console.WriteLine($"{emp.Nombre} {emp.Apellidos}, Depto: {emp.Departamento} , Salario: {emp.Salario}"); } Console.WriteLine("Agrupar empleados por departamento:"); var empleadosPorDepto = from emp in empleados.Lista group emp by emp.Departamento into deptGroup select new { Departamento = deptGroup.Key, Cantidad = deptGroup.Count() }; foreach (var emp in empleadosPorDepto) { Console.WriteLine($"Departamento: {emp.Departamento} , Cantidad: {emp.Cantidad}"); } bool hayAltosSueldos = empleados.Lista.Any(e => e.Salario > 30000); if(hayAltosSueldos) { Console.WriteLine("Existe al menos un empleado con un salario relativamente grande."); } bool todosConCorreoEdu = empleados.Lista.All(d => d.Correo.EndsWith("infotec.com")); if(todosConCorreoEdu) { Console.WriteLine("Todos los empleados tienen correo institucional."); } } } }
Construimos y ejecutamos:
$ dotnet build $ dotnet run
Salida:
Empleados mejor pagados: Veronica - 30000.00 Juan - 38000.00 Nombre y correo: Horacio - horacio.gomez.tor@infotec.com Veronica - veronica.uribe.gom@infotec.com Karla - karla.perez.per@infotec.com Juan - juan.archundia.lar@infotec.com Empleados [por salario ascendente]: Horacio Gomez Torres, Depto: 202 , Salario: 25000.00 Karla Perez Perez, Depto: 200 , Salario: 28000.00 Veronica Uribe Gomora, Depto: 204 , Salario: 30000.00 Juan Archundia Lara, Depto: 204 , Salario: 38000.00 Agrupar empleados por departamento: Departamento: 202 , Cantidad: 1 Departamento: 204 , Cantidad: 2 Departamento: 200 , Cantidad: 1 Existe al menos un empleado con un salario relativamente grande. Todos los empleados tienen correo institucional.
¡Hemos creado consultas básicas con LINQ!
Continuaremos con esta serie sobre C# y LINQ.
Enlaces:
https://codemonkeyjunior.blogspot.com/2026/06/linq-consultando-documentos-json.htmlhttps://codemonkeyjunior.blogspot.com/2025/12/linq-consultando-documentos-xml.html
https://codemonkeyjunior.blogspot.com/2025/11/linq-un-lenguaje-de-consulta-para-c.html

No hay comentarios:
Publicar un comentario