8 de mayo de 2015

Abrir XML con C# ListView

Se mostrara el contenido del archivo xml en un listView utilizando C#, el contenido del archivo xml es


  
    Pablo el primero
    Programador Cliente-Servidor
  
  
    Pablo el segundo
    Programador Web
  
  
en el evento Load() del formulario colocar este codigo
 listView1.View = View.Details;
 listView1.Clear();
 listView1.Columns.Clear();
 listView1.Columns.Add("", 400);
Utilizando XMLTextReader El primer ejemplo utiliza XMLTextReader para mostrar el formato del archivo xml, es decir, ademas de mostrar la información, se mostrara ordenada y con sus nodos tal cual esta codificado
private void buttonXML_Click(object sender, EventArgs e){
     
XmlTextReader reader = new XmlTextReader("prueba.xml");
 while (reader.Read())
 {
 switch (reader.NodeType)
  {
   case XmlNodeType.Element: // The node is an element.
   listView1.Items.Add("<" + reader.Name + ">");
   break;
   case XmlNodeType.Text: //Display the text in each element.
   listView1.Items.Add(reader.Value);
   break;
   case XmlNodeType.EndElement: //Display the end of the element.
   listView1.Items.Add("");
   break;
  }
 }
}
XMLDocument y XMLNodeList Para visualizar el contenido del archivo xml mostrado anteriormente en un listBox utilizando XMLDocument y XMLNodeList se tiene este codigo
private void BXML_Click(object sender, EventArgs e)
 {
  listView1.Clear();
  listView1.Columns.Clear();
  listView1.Columns.Add("prueba.xml", 400);

 XmlDocument xml = new XmlDocument();
 xml.Load("prueba.xml"); 

 XmlNodeList xnList = xml.SelectNodes("/personas/persona");
  foreach (XmlNode xn in xnList)
   {
    string nombre = xn["nombre"].InnerText;
    string ocupacion = xn["ocupacion"].InnerText;
    listView1.Items.Add(nombre);
    listView1.Items.Add(ocupacion);
   }
 }
pero si el archivo xml tiene la forma


  
  
 
este código te servirá
private void button1_Click(object sender, EventArgs e){
   listView1.Clear();
   listView1.Columns.Clear();
   listView1.Columns.Add("Nombre", 100, HorizontalAlignment.Left);
   
 XmlDocument xDoc = new XmlDocument();
  try
   {
    xDoc.Load("prueba2.xml");
    XmlNodeList personas = xDoc.GetElementsByTagName("personas");
    XmlNodeList lista = ((XmlElement)personas[0]).GetElementsByTagName("persona");
    int i = 0;

    foreach (XmlElement nodo in lista)
     {
      string nNombre = nodo.GetAttribute("id");
      listView1.Items.Add(nNombre);
      string nApellido1 = nodo.GetAttribute("nombre");
      listView1.Items.Add(nApellido1);

      string nApellido2 = nodo.GetAttribute("ocupacion");
      listView1.Items.Add(nApellido2);

      listView1.Items.Add("");

    i++;
     }
   }
   catch (Exception ex) { throw new ArgumentException(ex.Message); }
 }
XDocument - XAttribute - XElement esta solución fue una respuesta de un hilo de stackoverflow creado por mi, funciono bastante bien y no importa cual sea el documento xml, siempre va mostrar los nodos con sus respectivos nombres y los valores de estos
private void button1_Click(object sender, EventArgs e)
 {
  string xml =
@"

 
  Pablo el primero
  Programador Cliente-Servidor
 
 
  Pablo el segundo
  Programador Web
 
";

 XDocument doc = XDocument.Parse(xml);
 List ItemList = new List();
  foreach (XElement elem in doc.Elements())
   {
   AddNewItemToList(ItemList, elem);
   }
   listView1.Items.AddRange(ItemList.ToArray());
   }

private void AddNewItemToList(List ItemList, XElement elem)
 {
  string attributes = "";
  if (elem.HasAttributes)
   {
    foreach (XAttribute attr in elem.Attributes())
     {
      attributes += " " + attr.Name + "=\"" + attr.Value + "\"";
     }
    }

  if (elem.HasElements)
  {
   ItemList.Add(new ListViewItem("<" + elem.Name + attributes + ">"));
   foreach (XElement childElem in elem.Elements())
   {
    AddNewItemToList(ItemList, childElem);
   }
    ItemList.Add(new ListViewItem(""));
   }
   else
   {
    ItemList.Add(new ListViewItem("<" + elem.Name + attributes + ">" + elem.Value + ""));
   }
}
Linq to XML el segundo ejemplo utiliza Linq to XML para recuperar la información del xml pero no muestra el formato, es decir, no aparecerán los nodos, ante tal situación agregare items al listView a fin de representar los nodos del archivo pero...pero...esta solución funcionara solo para el archivo xml mostrado al principio de la entrada, por ejemplo si tienes otro xml con nombre de nodos diferentes pues ya no te funcionara, por ejemplo el código anterior no funcionaria con este xml


 
 God of War III 
 60 


...


...


este es el código, para este ejemplo no utilizare una clase que represente los nodos del archivo xml
private void buttonXML_Click(object sender, EventArgs e)
 {
  string path = "prueba.xml";
  listView1.Items.Clear();
       
  XElement doc = XElement.Load(path);
  // var result = from persona in doc.Descendants("persona")
  var result = from persona in doc.Elements("persona")
      select new
         {
          id = Convert.ToString(persona.Attribute("id").Value).Trim(),
          nombre = Convert.ToString(persona.Element("nombre").Value).Trim(),
          ocupacion = Convert.ToString(persona.Element("ocupacion").Value).Trim()
         };  

           foreach (var persona in result)
            {
             ListViewItem nombre = new ListViewItem("  " + persona.nombre + "  ");
             ListViewItem ocupacion = new ListViewItem("  " + persona.ocupacion + "  ");
             listView1.Items.Add("");
             listView1.Items.Add(nombre);
             listView1.Items.Add(ocupacion);
             listView1.Items.Add("");
             listView1.Items.Add("");
           }
 }
pero que pasa si el archivo xml tiene esta forma


  
  
 
entonces utilizamos la misma lógica para el código pero obtenemos el valor con Attribute
private void button2_Click(object sender, EventArgs e)
 {
   string path = "prueba2.xml";
   listView1.Items.Clear();

   XElement doc = XElement.Load(path);
   // var result = from persona in doc.Descendants("persona")
   var result = from persona in doc.Elements("persona")
      select new
       {
        id = Convert.ToString(persona.Attribute("id").Value).Trim(),
        nombre = Convert.ToString(persona.Attribute("nombre").Value).Trim(),
        ocupacion = Convert.ToString(persona.Attribute("ocupacion").Value).Trim()
        };

         foreach (var persona in result)
          {
           listView1.Items.Add("");
           listView1.Items.Add("");
          }
        }
Linq to XML Por ultimo se mostrara como utilizar una clase que represente el archivo xml que se desea mostrar, esta solución es la correcta por ser orientada a objetos pero como viste anteriormente no es la única e igualmente las soluciones anteriores funcionan en su cometido. De nuevo utilizamos el archivo xml mostrado al inicio de la entrada, para este ejemplo se crea una nueva clase de nombre persona.cs la cual contendra un metodo que recuperara toda la informacion del archivo xml en una lista de entidades, la clase quedaría de la siguiente manera
using System.Xml.Linq;

namespace pabletoreto.blogspot.com
{
 class persona
  {
   private int idPersona;
   private string nombrePersona;
   private string ocupacionPersona;

   public int _idPersona
    {
     get { return idPersona; }
     set { idPersona = value; }
    }
   public string _nombrePersona
    {
     get { return nombrePersona; }
     set { nombrePersona = value; }
    }
   public string _ocupacionPersona
    {
     get { return ocupacionPersona; }
     set { ocupacionPersona = value; }
    }

   public persona() { }
   public persona(int id, string nombre, string ocupacion) {
    this._idPersona = id;
    this._nombrePersona = nombre;
    this._ocupacionPersona = ocupacion;
   }

   public List leerXML( string path){
    var consulta =
      from valor in XElement.Load(path).Elements("persona")
      select new persona{
        _idPersona = Convert.ToInt32(Convert.ToString( valor.Attribute("id").Value ).Trim( ) ),
        _nombrePersona = Convert.ToString( valor.Element( "nombre" ).Value ).Trim( ),
        _ocupacionPersona = Convert.ToString(valor.Element( "ocupacion" ).Value ).Trim( )
      };
    List personas = consulta.ToList();
    return personas;
    }
  }
}
y desde el evento click de un botón colocamos este código
private void button5_Click(object sender, EventArgs e)
 {
  string path ="prueba.xml";
  persona ps = new persona();
   foreach( persona valor in ps.leerXML(path) ){
    ListViewItem nombre = new ListViewItem("  " + valor._nombrePersona + "  ");
    ListViewItem ocupacion = new ListViewItem("  " + valor._ocupacionPersona + "  ");
    listView1.Items.Add("");
    listView1.Items.Add(nombre);
    listView1.Items.Add(ocupacion);
    listView1.Items.Add("");
    listView1.Items.Add("");
   }
 }