2. Luego se mostrara información especifica del valor de un nodo(no todo el nodo, solo un valor dentro de este), se agregara, modificara y eliminara información dentro de un nodo, ya sea un valor o un atributo.
3. Por ultimo se muestra como consultar toda la información de un nodo(no solo un valor o atributo de este) como agregar y como eliminar todo un nodo no solo un valor o atributo de este.
Código Linq2 XML para leer ArchivoJuan juan@gmail.com 666666666 911111111 Luis luis@gmail.com 666777777 María maria@gmail.com 666888888 91222222
Existen varias formas en .NET C# para leer un fichero XML, acá expondremos 2 formas distintas aunque si fuera yo quien tuviese que elegir me quedaría con esta primera variante de código para leer un archivo XML.
Esta primera variante usa el método Descendants que existe en ambas clases (XElement y XDocument):
// Código para leer un fichero XML usando LINQ 2 XML private static void Linq2XmlLeerFicheroXmlConXElement() { XElement xmlContactos = XElement.Load("Contactos.xml"); //Obtener el Nombre de todos los contactos var contactosAll = from c in xmlContactos.Descendants("Contacto") select c.Element("Nombre").Value; //Obtener todos los contactos cuyo nombre comiencen con L var contactosL = from c in xmlContactos.Descendants("Contacto") where c.Element("Nombre").Value.StartsWith("L") select c; //Obtener todos los contactos que al menos uno de los Telefonos sea de Tipo Personal var contactosTelPers = from c in xmlContactos.Descendants("Contacto") where null != c.Elements("Telefono").Attributes("Tipo"). FirstOrDefault(t => t.Value == "Personal") select c; }
Otra variante de código para obtener el mismo resultado:
// Código para leer un fichero XML usando LINQ 2 XML private static void Linq2XmlLeerFicheroXml() { XDocument docContactos = XDocument.Load("Contactos.xml"); //Obtener el Nombre de todos los contactos var contactosAll = from c in docContactos.Elements("Contactos").Elements("Contacto") select c.Element("Nombre").Value; //Obtener todos los contactos cuyo nombre comiencen con L var contactosL = from c in docContactos.Elements("Contactos").Elements("Contacto") where c.Element("Nombre").Value.StartsWith("L") select c; //Obtener todos los contactos que al menos uno de los Telefonos sea de Tipo Personal var contactosTelPers = from c in docContactos.Elements("Contactos").Elements("Contacto") where null != c.Elements("Telefono").Attributes("Tipo"). FirstOrDefault(t => t.Value == "Personal") select c; }
Adicionar un elemento a nodos existentes con LINQ to XML
Existen varias formas en .NET C# para crear un nuevo elemento en un árbol XML, acá expondremos 2 formas distintas:
XElement.Add: Se describe por si solo, adiciona un nuevo elemento.
XElement.SetElementValue: Modifica, agrega o elimina un elemento.
Como vemos en el contenido del archivo XML de arriba, nuestro segundo contacto (Luis) tiene un elemento EMail asociado, imaginemos que queremos modificar el Email. Veamos las 2 variantes de código para obtener dicho resultado:
// Método XElement.Add // Código para adicionar un elemento usando Add (LINQ 2 XML) private static void Linq2XmlAddEmailUsandoAdd() { XElement xmlContactos = XElement.Load("Contactos.xml"); //Obtener el contacto con nombre Luis var contactoLuis = (from c in xmlContactos.Descendants("Contacto") where c.Element("Nombre").Value.ToUpper() == "LUIS" select c).FirstOrDefault(); if (contactoLuis != null) { string strXml = @"luis1@gmail.com "; contactoLuis.Add(XElement.Parse(strXml)); } }
Modificar un elemento de nodos existentes con LINQ to XML
Si usamos el código que hemos expuesto, en realidad no estamos modificando el Email, sino que estamos adicionando un nuevo Email, es decir para Luis tendríamos ahora 2 Mail, el que tenia anteriormente (luis@gmail.com) y el que recién acabamos de adicionar (luis1@gmail.com). Es decir que no logramos el resultado esperado.
Para lograrlo teníamos que haber eliminado el nodo y crearlo nuevamente con el valor correcto. Veamos ahora el código usando el segundo método:
// Método XElement.SetElementValue // Código para adicionar un elemento usando SetElementValue (LINQ 2 XML) private static void Linq2XmlAddEmailUsandoSetElementValue() { XElement xmlContactos = XElement.Load("Contactos.xml"); //Obtener el contacto con nombre Luis var contactoLuis = (from c in xmlContactos.Descendants("Contacto") where c.Element("Nombre").Value.ToUpper() == "LUIS" select c).FirstOrDefault(); if (contactoLuis != null) contactoLuis.SetElementValue("EMail", luis2@gmail.com); }
Usando este segundo código, sí logramos el resultado esperado, porque el método SetElementValue lo que hace es buscar dentro del elemento contactoLuis, el nodo o elemento EMail y si existe modifica su valor, en caso contrario lo adiciona. si por el contrario quisiéramos modificar todos los atributos de todos los nodos
XDocument xmlFile = XDocument.Load("Contactos.xml"); var query = from c in xmlFile.Elements("Contactos").Elements("contacto") select c; foreach (XElement contacto in query) { contacto.Attribute("attr1").Value = "MyNewValue"; } xmlFile.Save("Contactos.xml");
Si nuestro objetivo hubiese sido eliminar el nodo Email, podríamos haber usado el método SetElementValue con el segundo parámetro en null:
contactoLuis.SetElementValue("EMail", null);
XElement.SetAttributeValue
Al igual que el método SetElementValue, existe un método SetAttributeValue que establece, agrega o elimina un atributo de un elemento. Pero veamos un ejemplo donde le cambiemos el atributo del teléfono que tiene Luis (cambiarlo de Móvil a Trabajo):
// Código para modificar atributo usando SetAttributeValue (LINQ 2 XML) private static void Linq2XmlSetAttributeValue() { XElement xmlContactos = XElement.Load("Contactos.xml"); //Obtener el contacto con nombre Luis var contactoLuis = (from c in xmlContactos.Descendants("Contacto") where c.Element("Nombre").Value.ToUpper() == "LUIS" && c.Element("Telefono").HasAttributes select c).FirstOrDefault(); if (contactoLuis != null) contactoLuis.Element("Telefono").SetAttributeValue("Tipo", "Trabajo"); }
Nota: En el código anterior, en la consulta hemos preguntado por la propiedad HasAttributes, en realidad carece de sentido en nuestro ejemplo preguntar por dicha propiedad, porque si el elemento Telefono no tuviese atributos igual crearía el atributo Tipo. De todas formas me pareció interesante incorporar la propiedad para que el lector sepa de su existencia, en ocasiones suele ser de utilidad.
De similar manera que sucede con el SetElementValue, si quisiéramos eliminar un atributo usaríamos el método SetAttributeValue con el segundo parámetro nulo (null).
Seleccionar Información de Nodo Completo
private void buscarEnXML(string idCon) { XDocument miXML = XDocument.Load(@"C:\Prueba\MiDoc.xml"); var nombreusu = from nombre in miXML.Elements("Contactos").Elements("Contacto") where nombre.Attribute("Id_Empleado").Value == idCon //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 } }
Agregar Nuevo Nodo a documento XML
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"); }
Eliminar Nodo de documento XML
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"); }