3.2.Agregar un filtro al xml.

En el anterior post vimos como utilizar un xml como un dataSet, en éste veremos como agregar un filtro sobre los datos del xml.

Si os acordáis utilizamos linq para realizar la consulta, linq no es más que un conjunto de herramientas de Microsoft para realizar todo tipo de consultas a distintas fuentes, en nuestro caso a un xml.
Si recordáis la consulta de nuestro anterior post era la siguiente:

var q = from c in xdoc.Descendants("food")

En ella le indicábamos que nos devolviera todos los subnodos del nodo llamado food.

Hoy cambiaremos esta consulta para que filtre por el campo nombre y para esto agregaremos un parámetro al informe.

Nos basaremos en nuestro anterior informe, si no leíste mi anterior post lo tenéis aquí:

http://axlearn2012.blogspot.com.es/2014/03/3_29.HTML


Vamos a modificar nuestro método xmlDataSet para agregarle un where para que filtre nuestra consulta por el nombre que el usuario haya seleccionado.

Os escribo en verde las modificaciones que realizaremos a este método.

public partial class XMLReport
{
    [DataMethod(), PermissionSet(SecurityAction.Assert, Name = "FullTrust")]
    public static DataTable xmlDataSet(string name)
    {
        DataTable dt = new DataTable();

        dt.Columns.Add("name", typeof(string));
        dt.Columns.Add("price", typeof(string));
        dt.Columns.Add("description", typeof(string));
        dt.Columns.Add("calories", typeof(string));

        XDocument xdoc = XDocument.Load("http://www.w3schools.com/xml/simple.xml");

        var q = from c in xdoc.Descendants("food")
                     where (c.Element("name").Value == name || string.IsNullOrEmpty(name))
             
                select new
                {
                    name          = c.Element("name").Value,
                    price           = c.Element("Price").Value,
                    description = c.Element("description").Value,
                    calories      = c.Element("calories").Value
                };

                foreach (var obj in q)
                {
                    dt.Rows.Add(obj.name,
                                          obj.price,
                                          obj.description,
                                          obj.calories);
                }

        return dt;   
    }
}

Las modificaciones han sido mínimas, simplemente le hemos agregado un parámetro que será utilizado en el where que hemos creado.


El siguiente paso será crearnos un nuevo método que será el encargado de recuperar los datos que se mostrarán en el lookup.

 
Modificaremos el nuevo método y escribimos lo que sigue.

[DataMethod(), PermissionSet(SecurityAction.Assert, Name = "FullTrust")]
public static DataTable nameLookup()
{
        DataTable dt = new DataTable();

        dt.Columns.Add("name", typeof(string));

        XDocument xdoc = XDocument.Load("http://www.w3schools.com/xml/simple.xml");

        XNamespace space = xdoc.Root.GetDefaultNamespace();

        IEnumerable<string> q = xdoc.Descendants("food").Descendants("name").Select(pn => pn.Value).Distinct().ToList();

        foreach (string name in q)
        {
            dt.Rows.Add(name);
        }
        return dt;
}

Las estructura del método nos resultará familiar, ya que es similar al método que creamos anteriormente para devolver los datos del xml.

Analicemos un poco lo que hace esto.

Esta primera parte no tiene secretos para nosotros, nos crea una variable de tipo dataTable y le agrega una columna llamada name, luego nos almacenamos en una variable de tipo XDocument el xml.

DataTable dt = new DataTable();

dt.Columns.Add("name", typeof(string));

XDocument xdoc = XDocument.Load("http://www.w3schools.com/xml/simple.xml");


La siguiente línea nos creará un enumerador de tipo string con el valor de los subnodos llamados name del nodo principal food.

IEnumerable<string> q = xdoc.Descendants("food").Descendants("name").Select(pn => pn.Value).Distinct().ToList();

Agregará estos valores recuperaros a la variable datatable que será devuelta.

foreach (string name in q)
{
      dt.Rows.Add(name);
};



Ahora mismo deberíais tener creado una clase con dos métodos, algo similar al siguiente código:

public partial class XMLReport
{
    [DataMethod(), PermissionSet(SecurityAction.Assert, Name = "FullTrust")]
    public static DataTable xmlDataSet(string name)
    {
        DataTable dt = new DataTable();

        dt.Columns.Add("name", typeof(string));
        dt.Columns.Add("price", typeof(string));
        dt.Columns.Add("description", typeof(string));
        dt.Columns.Add("calories", typeof(string));

        XDocument xdoc = XDocument.Load("http://www.w3schools.com/xml/simple.xml");

        var q = from c in xdoc.Descendants("food")
                     where (c.Element("name").Value == name || string.IsNullOrEmpty(name))
             
                select new
                {
                    name          = c.Element("name").Value,
                    price           = c.Element("Price").Value,
                    description = c.Element("description").Value,
                    calories      = c.Element("calories").Value
                };

                foreach (var obj in q)
                {
                    dt.Rows.Add(obj.name,
                                          obj.price,
                                          obj.description,
                                          obj.calories);
                }

        return dt;   
    }

    [DataMethod(), PermissionSet(SecurityAction.Assert, Name = "FullTrust")]
    public static DataTable nameLookup()
   {
        DataTable dt = new DataTable();

        dt.Columns.Add("name", typeof(string));

        XDocument xdoc = XDocument.Load("http://www.w3schools.com/xml/simple.xml");

        XNamespace space = xdoc.Root.GetDefaultNamespace();

        IEnumerable<string> q = xdoc.Descendants("food").Descendants("name").Select(pn => pn.Value).Distinct().ToList();

        foreach (string name in q)
        {
            dt.Rows.Add(name);
        }
        return dt;
    }
 }


Acordaos de implementar la solución.



Ahora tocaremos el informe para agregar este lookup.

Agregaremos un dataSet al que llamaremos namelookup (Este será el dataset que guardará la lista de valores para nuestro lookup).

 
En la siguiente imagen podemos ver como quedarán las propiedades del nuevo dataset.
 
 
En la propiedad Query seleccionaremos el método namelookup-
 

 


En caso de que vuestro nuevo parámetro no aparezca generad la solución y refrescad los dataSets.

 
 
A estas alturas ya deberíais ver el nuevo parámetro.
 
 
Si os fijais en el datasetLookup tenemos un sólo campo que será el que almacenará los valores del lookup.
 
Si ahora intentáramos hacer una previsualización veríamos que aparece nuestro parámetro, pero no tiene el aspecto que nos interesaría, ya que todavía no esta asociada al datasetlookup.
 
 
 
Para arreglar el lookup  iremos a las propiedades del parámetro en el nodo parámetros del report.
 

La propiedad que nos interesa será la de Values , al presionar ésta nos abrirá un formulario donde podremos introducir los datos.


Para este ejemplo los desplegables del formulario solamente nos permitirán una opción.

Explicaré las opciones del formulario:

DataSet: El dataSet de donde el parámetro debe tomar el valor.
ValueField: El campo del que debe tomar el valor.
LabelField: El campo del que debe tomar la etiqueta.

Una vez hecho esto nuestro parámetro tendrá un aspecto tipo lookup.

 
 
Y lo más importante nos desplegará los posibles valores del campo name del fichero xml.
 
 
Ahora al seleccionar un valor el informe únicamente mostrará el resultado para ese valor.
 

 
 

Comentarios