sábado, 1 de marzo de 2008

LinQ to XML


LinQ to Sql (Arquitectura de capas):


LinQ to XML en pocas palabras nos permite leer, definir y escribir datos en estructura XML. Con esto podemos acceder a información desde diferentes canales, como conectarnos a un directorio de archivos y abrir un xml o rescatar un xml entregado desde un servicio web o desde cualquier otro canal que nos entregue un archivo xml.

Bueno si observamos en el ejemplo siguiente podemos rescatar de forma más facil la información de un nodo que con la API de XmlReader/XmlWriter. Una de las ventajas que caracterizan este tipo de objeto es que es más eficiente y usa menos memoria que la API DOM que tiene XmlDocument.

Ahora al ejemplo:

El ejemplo consistirá en capturar un archivo xml y realizar acciones sobre este. Si bien es cierto podemos obtener, como dijimos, un xml de muchas partes, desde un procedimiento almacenado usando un for xml explicit, construyendo uno a raiz de un resultas, rescatando uno desde un WebService, etc.
Nosotros lo que haremos será utilizar el ejemplo que definimos en LinQ to Object para generar nuestro archivo xml y luego vamos a realizar acciones sobre este, en el caso de que no quieran tomar el ejemplo anterior les pongo a dispocición un xml de ejemplo.

<?xml version='1.0'?>
<Datos>
<dato edad='35'>
<nombre>Mario</nombre>
<appPrimero>Roa</appPrimero>
<appSegundo>Vidal</appSegundo>
<fNacimiento>28/09/1972 0:00:00</fNacimiento>
</dato>
<dato edad='37'>
<nombre>Juan</nombre>
<appPrimero>Paco</appPrimero>
<appSegundo>De la Mar</appSegundo>
<fNacimiento>10/11/1970 0:00:00</fNacimiento>
</dato>
<dato edad='32'>
<nombre>Pedro</nombre>
<appPrimero>Manuel</appPrimero>
<appSegundo>Gutierrez</appSegundo>
<fNacimiento>10/12/1975 0:00:00</fNacimiento>
</dato>
</Datos>

Ustedes solo escriben las líneas que necesiten, ya que pueden leer directamente el Xml desde un archivo de directorio, utilizando el objeto XDocument.Load(URL), que se encuentra en el espacio de nombre System.Xml.Linq, por lo cual en la cabecera del archivo de formulario debemos agregar los siguientes espacios de nombre:

using System.Xml.Linq;

Nosotros lo que haremos en este caso será parsear el string del xml a XDocument para poder operar con el, con lo cual, agregaremos un botón a la aplicación para realizar nuestro ejercicio, como se muestra a continuación:

Primero crearemos un método en forma de función que nos retornará el string con el xml que contendrá la información de la lista creada, de la siguiente forma:

string fnXmlObtener() {
string sXml = "";
try{
sXml = "<?xml version='1.0'?>";
sXml += "<Datos>";
for (int i = 0; i < lstPersona.Count; i++)
{
sXml += "<dato edad='" + lstPersona[i].Edad.ToString() + "'>";
sXml += "<nombre> + lstPersona[i].Nombre.ToString() + "</nombre>";
sXml += "<appPrimero>" + lstPersona[i].ApellidoPrimero.ToString() + "</appPrimero>";
sXml += "<appSegundo>" + lstPersona[i].ApellidoSegundo.ToString() + "</appSegundo>";
sXml += "<fNacimiento>" + lstPersona[i].FechaNacimiento.ToString() + "</fNacimiento>";
sXml += "</dato>";
}
sXml += "</Datos>";
}
catch (Exception ex) { throw ex; }
return sXml;
}

Ahora vamos a ponerle la lógica al método que atiende el evento click del botón agregado, al cual he llamado btnXml. En este método vamos a agregar dos tipos de búsqueda: Búsqueda por Atributo y Búsqueda por elemento.
  1. Búsqueda por atributo. Esta permitirá a través del atributo edad rescatar los elementos asociados al nodo dato del xml con el que estamos trabajando.
  2. Búsqueda por elemento. Esta permite a través de un elemento, rescatar la información deseada.
1 - Búsqueda por atributo.
En este caso, se realiza la búsqueda comparando el atributo edad asociado al nodo dato. Asocio el código de llamada al xml si no desearan seguir con el ejercicio:

private void btnXml_Click(object sender, EventArgs e)
{
try
{
string sMsg = "";
string sXml = fnXmlObtener();

// --------------------------------------------------------------------------
// Aqui debería ir la llamada al archivo en un directorio
// XDocument xmlD = XDocument.Load(dirPath);
XDocument xmlD = XDocument.Parse(sXml);
// --------------------------------------------------------------------------

var dato = from d in xmlD.Descendants("dato")
where (d.Attribute("edad").Value == this.txtEdad.Text)
select new
{
nombre = d.Element("nombre").Value, appPrimero = d.Element("appPrimero").Value,
appSegundo = d.Element("appSegundo").Value, fNacimiento = d.Element("fNacimiento").Value
};
foreach (var d in dato){
sMsg = "Nombre: " + d.nombre + " " + d.appPrimero + " " + d.appSegundo + "\r\r" +
"Fecha de nacimiento " + d.fNacimiento + "\r\r";
}
MessageBox.Show(sMsg);

}
catch (Exception ex) {
MessageBox.Show(ex.Message);
}
}

Comentemos el código: Si se observa en la búsqueda realizamos la llamada al nodo en el que deseamos realizar las consultas, una vez que este este definido, mediante la instrucción Value del XAttribute que deseamos comparar, rescatamos la información de los elementos de los nodos que coinciden.

2 - Búsqueda por elemento.
Esta acción busca directamente en los elementos del nodo, para este caso dato, ya que se lo estamos indicando, cuando encuentra coincidentes los despliega de la misma forma que cuando buscaba por elemento.

private void btnXml_Click(object sender, EventArgs e)
{
try
{
string sMsg = "";
string sXml = fnXmlObtener();

// --------------------------------------------------------------------------
// Aqui debería ir la llamada al archivo en un directorio
// XDocument xmlD = XDocument.Load(dirPath);
XDocument xmlD = XDocument.Parse(sXml);
// --------------------------------------------------------------------------

var dato = from d in xmlD.Descendants("dato")
where (d.Element("nombre").Value.IndexOf(this.txtNombreBusqueda.Text) != -1)
select new
{
nombre = d.Element("nombre").Value, appPrimero = d.Element("appPrimero").Value,
appSegundo = d.Element("appSegundo").Value, fNacimiento = d.Element("fNacimiento").Value
};

foreach (var d in dato){
sMsg = "Nombre: " + d.nombre + " " + d.appPrimero + " " + d.appSegundo + "\r\r" +
"Fecha de nacimiento " + d.fNacimiento + "\r\r";
}
MessageBox.Show(sMsg);
}
catch (Exception ex) {
MessageBox.Show(ex.Message);
}
}

Bueno amigos a probar y espero que todo funcione bien

No hay comentarios: