sábado, 18 de junho de 2016

using System.Xml.Linq

So, for learning purpose, imagine that you need to generate something like this:
 <bills>  
 <bill>  
      <value>1270.45</value>  
      <date>  
           <day>21</day>  
           <month>12</month>  
           <year>2012</year>  
      </date>  
      <from> Space Shop </from>  
      <to> Bill Gates </to>  
      <status> Closed </status>  
 </bill>  
 <bill>  
      <value>1245.55</value>  
      <date>  
           <day>25</day>  
           <month>11</month>  
           <year>2011</year>  
      </date>  
      <from> Business Center </from>  
      <to> Steve Jobs </to>  
      <status> Closed </status>  
 </bill>  
 </bills>  
It's not my favorite type to write xml(when i can choose), it shows verbosity and blah.... and once you have it, now you need to show this for people: Bill: From: ................. To: .............. (...) It can be boring depending on how you do it. Xml.Linq can do this with elegance, let's see: 1) Creating Bill class
 public enum StatusEnum { Closed, Open, Removed };  
   class Bill  
   {  
     public decimal Value { get; set; }  
     public DateTime Date { get; set; }  
     public string From { get; set; }  
     public string To { get; set; }  
     public StatusEnum Status { get; set; }  
     public Bill(decimal Value, DateTime Date, string From, string To, StatusEnum Status)  
     {  
       this.Value = Value;  
       this.Date = Date;  
       this.From = From;  
       this.To = To;  
       this.Status = Status;  
     }  
   }  
2) Creating objects:
 private static List<Bill> Bills = new List<Bill>()  
     {  
       new Bill (1250.75m, new DateTime(2012, 12, 21), "Space Shop", "Bill Gates", StatusEnum.Closed),  
       new Bill (1785.55m, new DateTime(2007, 10, 15), "Business Center", "Steve Jobs", StatusEnum.Closed),  
       new Bill (193.75m, new DateTime(2012, 12, 21), "Gym", "Arnold", StatusEnum.Removed),  
       new Bill (5845.70m, new DateTime(2012, 12, 21), "Chanel", "Gisele", StatusEnum.Open)  
     };  
3) Generating Xml:
 XDocument docBillsXml =  
         new XDocument(new XElement("bills",  
                 (from bill in Bills  
                 orderby bill.Value descending,  
                     bill.Date descending  
                 select new XElement("bill",  
                   new XElement("value", bill.Value),  
                   new XElement("date", new XElement("day", bill.Date.Day),  
                              new XElement("month", bill.Date.Month),  
                              new XElement("year", bill.Date.Year)),  
                   new XElement("from", bill.From),  
                   new XElement("to", bill.To),  
                   new XElement("status", bill.Status.ToString())  
                 )  
               )  
         ));  
So, here we create a Document(bills) and for each object we generate an element(bill). Ordering by the value of the bill and the date, both descending (ascending is default). So the bills with highest values comes first and inside of that order the newest bills comes first. Now we have docBillsXml and we need show this to people. The first way is using a simple foreach:
 var bills = docBillsXml.Element("bills").Elements("bill");  
       foreach(var bill in bills)  
       {  
         Console.WriteLine("Bill:");  
         Console.WriteLine("\tFrom: {0}", bill.Element("from").Value);  
         Console.WriteLine("\tTo: {0}", bill.Element("to").Value);  
         var date = bill.Element("date");  
         Console.WriteLine("\tDate: {0}\\{1}\\{2}", date.Element("day").Value,  
                              date.Element("month").Value,  
                              date.Element("year").Value);  
         Console.WriteLine("\tValue: {0}", bill.Element("value").Value);  
         Console.WriteLine("\tStatus: {0}", bill.Element("status").Value.ToString());  
         Console.Write("\n");  
       }  
using .Element("bills") we get the root element and with Elements("bill") we get all the bills. The second way to show this to people is using projection:
 var billsWithLinq = from bill in docBillsXml.Descendants("bill")  
                 where (bill.Element("status").Value.ToString().StartsWith("Cl"))  
                 select new  
                 {  
                   Company = bill.Element("from").Value,  
                   Client = bill.Element("to").Value  
                 };  
       foreach(var bill in billsWithLinq)  
       {  
         Console.WriteLine("Bill:");  
         Console.WriteLine("\tClient: {0}", bill.Client);  
         Console.WriteLine("\tCompany: {0}", bill.Company);  
         Console.Write("\n");  
       }  
with . Descendants("bill") we get all the bill elements. Using Where to filter and get the closed bills. To Think: if we insert the following line of code between the creation of docBillsXml and the exhibition, New Client will be in the exhibition?
 Bills.Add(new Bill(200.75m, new DateTime(2016, 01, 21), "New", "New Client", StatusEnum.Removed));  
suggestions-> leave comments. TY. More on:
https://msdn.microsoft.com/pt-br/library/system.xml.linq(v=vs.110).aspx
https://app.pluralsight.com/library/courses/linq-fundamentals/table-of-contents