Monday, July 16, 2012

Linq to XML

Hi readers

This post is about using Linq to XML to create a small Employee Management System.
This post will explain how to add delete update and query an XML document which contains information of employees.
The post will contain the basic coding needed and you can download the complete sample HERE First we'll see the structure of the XML we are going to use.

<?xml version="1.0" encoding="utf-8"?>
<Employees>
  <Employee ID="1">
    <Name>Saman</Name>
    <Department>Delivery</Department>
  </Employee>
  <Employee ID="2">
    <Name>Nimal</Name>
    <Department>Delivery</Department>
  </Employee>
</Employees>
 
For this I'm using a class called Employee. You can do this with or without a class but using a class is a standard and easy way. This class is used to transfer data between the UI and the EmployeeManager class. The interaction between the XML file and the program are done using Linq.

This the class diagram for the Employee and the Employee Manager Class

Well lets got to the coding part The Employee class is very simple just three attributes

public class Employee
{
//attribute ID
public int ID { get; set; }

//Element Name
public string Name { get; set; }

//Element Department
public string Department { get; set; }
}

Now the Employee Manager Class

public class EmployeeManager
{
    /// <summary>
    /// The path of the XML file 
    /// </summary>
    private string XMLFile;

    /// <summary>
    /// Employee Manager is used to handle the interaction between the XML file
    /// and the application
    /// </summary>
    /// <param name="file">The Location of the XML File</param>
    public EmployeeManager(string file)
    {
        XMLFile = file;

        //create the XML file if it doest exist
        if (!File.Exists(XMLFile))
        {
            //As the file is not there a new XML Document is created
            //Blank space is used to create an empty tag
            XDocument document = new  XDocument(
                                        new XElement("Employees","")
                                      );
            document.Save(XMLFile);
        }
    }

    /// <summary>
    /// Add an Employee to the XML file
    /// </summary>
    /// <param name="newEmployee">The Employee to be added</param>
    /// <returns>True if Success false otherwise</returns>
    public bool addEmployee(Employee newEmployee)
    {
        try
        {
            //load the xml file 
            XDocument document = XDocument.Load(XMLFile);
            //Get create a new Employee Element
            XElement employee = new XElement("Employee");
            //Set the value for the attribute
            employee.SetAttributeValue("ID",newEmployee.ID);
            //set the value for the child elements
            employee.Add(new XElement("Name", newEmployee.Name));
            employee.Add(new XElement("Department", newEmployee.Department));
            //add the created Employee element to the root element Employee
            document.Element("Employees").Add(employee);
            //Save the XML file so that the new Employee will be added
            document.Save(XMLFile);
            //Return to if success
            return true;
        }
        catch (Exception)
        {
            //return false if any exception occur
            return false;
        }

    }

    /// <summary>
    /// Delete an Employee from the XML file
    /// </summary>
    /// <param name="EmployeeID">ID of the Employee to be Deleted</param>
    /// <returns>True if Success false otherwise</returns>
    public bool deleteEmployee(int EmployeeID)
    {
        try
        {
            //Load the XML document
            XDocument document = XDocument.Load(XMLFile);
            //Get the Root tag Employees and get the Employee element to be deleted
            document.Element("Employees").Elements("Employee").FirstOrDefault
                (
                    //in here we are getting the first or default so if no element
                    //is there we'll get an exception
                    //We are comparing the attribute here
                    X => X.Attribute("ID").Value.Trim() == EmployeeID.ToString()
                    //the remove method deletes the employee
                ).Remove();
            //saving the changes to the XML file
            document.Save(XMLFile);
            return true;
        }
        catch (Exception)
        {
            return false;
        }
    }

    /// <summary>
    /// Update the attributes of an Employee
    /// </summary>
    /// <param name="updatedEmployee">Employee Object with Updated Values</param>
    /// <returns>True if Success false otherwise</returns>
    public bool updateEmployee(Employee updatedEmployee)
    {
        try
        {
            //Load the file
            XDocument document = XDocument.Load(XMLFile);
            //Update the child element values for the selected employee
            //you can use setAttribute method if you want to set an attributes value 
            document.Element("Employees").Elements("Employee").FirstOrDefault
                (
                    X => X.Attribute("ID").Value.Trim() == updatedEmployee.ID.ToString()
                ).SetElementValue("Name", updatedEmployee.Name);

            document.Element("Employees").Elements("Employee").FirstOrDefault
                (
                    X => X.Attribute("ID").Value.Trim() == updatedEmployee.ID.ToString()
                ).SetElementValue("Department", updatedEmployee.Department);
            //save changes to the xml file
            document.Save(XMLFile);
            return true;
        }
        catch (Exception)
        {
            return false;
        }
    }

    /// <summary>
    /// Get a list of All The employees in the 
    /// </summary>
    /// <returns>List of all Employees</returns>
    public List<Employee> getAllEmployees()
    {
        //Create an empty List to store the employee object
        List<Employee> empList = new List<Employee>();

        XDocument document = XDocument.Load(XMLFile);
        //here we are reading all the Employee values and create objects
        //and add it to the list
        foreach (XElement employee in document.Element("Employees").Elements("Employee"))
        {
            Employee emp = new Employee();
            emp.ID = Convert.ToInt32(employee.Attribute("ID").Value.Trim());
            emp.Name = employee.Element("Name").Value.Trim();
            emp.Department = employee.Element("Department").Value.Trim();
            empList.Add(emp);
        }
        //return the list
        return empList;
    }

    /// <summary>
    /// Get a selectes employee from the XML file
    /// </summary>
    /// <param name="ID">ID of the Employee</param>
    /// <returns>Employee object for the given ID</returns>
    public Employee getEmployee(int ID)
    {
        try
        {
            XDocument document = XDocument.Load(XMLFile);
            //Here we are selecting a single employee element and retrive its element values and
            //create a Employee object from it
            XElement employee = document.Element("Employees").Elements("Employee").FirstOrDefault(
                X => X.Attribute("ID").Value.Trim() == ID.ToString()
                );

            Employee selectedEmployee = new Employee() { 
                ID = Convert.ToInt32(employee.Attribute("ID").Value.Trim()),
                Name=employee.Element("Name").Value.Trim(),
                Department=employee.Element("Department").Value.Trim() 
            };
            //return the employe object
            return selectedEmployee;
        }
        catch (Exception)
        {
            //return null if no employee found with given ID
            return null;
        }

    }
}
This is the coding part.
Now you can create a UI like this and access the Employee Manager class and get things done.

Sample UI
 

You can download the complete sample HERE
Please leave a comment if you like the post 
Happy Coding :)
Guruparan Giritharan.