Tutorial : Linq to Xml
Ce tutorial a pour but de montrer comment manipuler un fichier à l'aide de Linq to Xml.
A travers cet exemple on pourra voir la création, la mise à jour, la suppression et la recherche dans un document xml.
1. Créer un nouveau site web
- Fichier, Nouveau site web
2. Ajouter la classe Voiture
Clique droit sur le nom du site, ajouter un nouvel élément, classe : Voiture.cs
Y ajouter les propriétés suivantes :
Résultat :
//----------------------------------------------------------------------- // <copyright file="Voiture.cs" company="CNED"> // Copyright (c) PHN. All rights reserved. // </copyright> // <author>PHN</author> // <date>07/06/2010</date> //----------------------------------------------------------------------- using System; using System.ComponentModel; using System.Web; using System.Web.Services; using System.Web.Services.Protocols; /// <summary> /// Voiture Class /// </summary> [Serializable] public class Voiture { #region CONSTANTES /// <summary> /// Noeud Voiture dans le fichier XML /// </summary> public const string VOITURE = "VOITURE"; /// <summary> /// ID dans le fichier xml /// </summary> public const string ID = "ID"; /// <summary> /// DATE_ACHAT dans le fichier XML /// </summary> public const string DATE_ACHAT = "DATE_ACHAT"; /// <summary> /// MARQUE dans le fichier XML /// </summary> public const string MARQUE = "MARQUE"; /// <summary> /// POIDS dans le fichier XML /// </summary> public const string POIDS = "POIDS"; /// <summary> /// PRIX dans le fichier XML /// </summary> public const string PRIX = "PRIX"; #endregion #region CONSTRUCTEUR /// <summary> /// Initializes a new instance of the Voiture class /// </summary> public Voiture() { } #endregion #region PROPRIETES /// <summary> /// Gets or sets Id /// </summary> public long Id { get; set; } /// <summary> /// Gets or sets Marque /// </summary> public string Marque { get; set; } /// <summary> /// Gets or sets Poids /// </summary> public int Poids { get; set; } /// <summary> /// Gets or sets DateAchat /// </summary> public DateTime DateAchat { get; set; } /// <summary> /// Gets or sets Prix /// </summary> public double Prix { get; set; } #endregion }
1. 3. Ajouter la classe VoitureService.cs qui contiendra la liste des méthodes avec les méthodes suivantes :
- GetAll
- GetById
- Update
- Insert
- Delete
- GetByMarque
- GetNewId
Ne pas oublier de rajouter les using suivants :
using System.Collections.Generic; using System.Linq; using System.Xml.Linq;
-
GetAll
-
#region GetAll /// <summary> /// Retourne toutes les voitures /// </summary> /// <param name="xmlFile">Le nom du fichier Xml</param> /// <returns>Une liste de voitures</returns> public IList<Voiture> GetAll(string xmlFile) { IList<Voiture> lsVoitures = null; XDocument xmlDoc = XDocument.Load(xmlFile); lsVoitures = (from voiture in xmlDoc.Descendants(Voiture.VOITURE) select new Voiture { Id = Convert.ToInt32(voiture.Element(Voiture.ID).Value), DateAchat = Convert.ToDateTime(voiture.Element(Voiture.DATE_ACHAT).Value), Marque = voiture.Element(Voiture.MARQUE).Value, Poids = Convert.ToInt32(voiture.Element(Voiture.POIDS).Value), Prix = Convert.ToDouble(voiture.Element(Voiture.PRIX).Value) } ).ToList<Voiture>(); return lsVoitures; } #endregion
-
GetById
-
#region GetById /// <summary> /// Retourne une voiture en fonction de son identifiant /// </summary> /// <param name="id">Identifiant de la voiture</param> /// <param name="xmlFile">Emplacement du fichier Xml</param> /// <returns>Une voiture</returns> public Voiture GetById(long id, string xmlFile) { Voiture theVoiture = new Voiture(); XDocument xmlDoc = XDocument.Load(xmlFile); theVoiture = (from voiture in xmlDoc.Descendants(Voiture.VOITURE) where voiture.Element(Voiture.ID).Value == id.ToString() select new Voiture { Id = Convert.ToInt32(voiture.Element(Voiture.ID).Value), DateAchat = Convert.ToDateTime(voiture.Element(Voiture.DATE_ACHAT).Value), Marque = voiture.Element(Voiture.MARQUE).Value, Poids = Convert.ToInt32(voiture.Element(Voiture.POIDS).Value), Prix = Convert.ToDouble(voiture.Element(Voiture.PRIX).Value) } ).Single<Voiture>(); return theVoiture; } #endregion
-
Insert
-
#region Insert /// <summary> /// Insertion d'une nouvelle voiture /// </summary> /// <param name="voiture">La nouvelle voiture</param> /// <param name="flux">Flux du fichier XML</param> /// <returns>true si ok, sinon false</returns> public bool Insert(Voiture voiture, string flux) { try { XElement doc = XElement.Load(flux); voiture.Id = this.GetNewId(flux); XElement newVoiture = new XElement( Voiture.VOITURE, new XElement(Voiture.ID, voiture.Id), new XElement(Voiture.DATE_ACHAT, voiture.DateAchat.ToString("dd/MM/yyyy")), new XElement(Voiture.MARQUE, voiture.Marque), new XElement(Voiture.POIDS, voiture.Poids), new XElement(Voiture.PRIX, voiture.Prix)); doc.Add(newVoiture); doc.Save(flux); return true; } catch (Exception) { return false; } } #endregion
-
Update
-
#region Update /// <summary> /// Mise à jour d'une voiture /// </summary> /// <param name="voiture">La voiture à mettre à jour</param> /// <param name="flux">Flux du fichier XML</param> /// <returns>true si ok, sinon false</returns> public bool Update(Voiture voiture, string flux) { try { XDocument xmlDoc = XDocument.Load(flux); IEnumerable<XElement> theVoiture = from voit in xmlDoc.Descendants(Voiture.VOITURE) where ((string)voit.Element(Voiture.ID)).Equals(voiture.Id.ToString()) select voit; foreach (XElement xe in theVoiture) { xe.SetElementValue(Voiture.DATE_ACHAT, voiture.DateAchat.ToString("dd/MM/yyyy")); xe.SetElementValue(Voiture.MARQUE, voiture.Marque); xe.SetElementValue(Voiture.POIDS, voiture.Poids); xe.SetElementValue(Voiture.PRIX, voiture.Prix); } xmlDoc.Save(flux); return true; } catch (Exception) { return true; } } #endregion
-
Delete
-
#region Delete /// <summary> /// Suppression d'une voiture /// </summary> /// <param name="voiture">La voiture à supprimer</param> /// <param name="flux">Flux du fichier XML</param> /// <returns>true si ok, sinon false</returns> public bool Delete(Voiture voiture, string flux) { try { XElement doc = XElement.Load(flux); IEnumerable<XElement> voitureToDelete = from voit in doc.Elements(Voiture.VOITURE) where voit.Element(Voiture.ID).Value == voiture.Id.ToString() select voit; foreach (XElement xe in voitureToDelete) { xe.Remove(); } doc.Save(flux); return true; } catch (Exception) { return false; } } #endregion
-
GetByMarque
-
#region GetByMarque /// <summary> /// Retourne une voiture en fonction de sa marque /// </summary> /// <param name="marque">Marque de la voiture</param> /// <param name="xmlFile">Emplacement du fichier Xml</param> /// <returns>Une liste de voitures</returns> public IList<Voiture> GetByMarque(string marque, string xmlFile) { IList<Voiture> lsVoiture = null; XDocument xmlDoc = XDocument.Load(xmlFile); lsVoiture = (from voiture in xmlDoc.Descendants(Voiture.VOITURE) where voiture.Element(Voiture.MARQUE).Value.ToLower().Contains(marque) select new Voiture { Id = Convert.ToInt32(voiture.Element(Voiture.ID).Value), DateAchat = Convert.ToDateTime(voiture.Element(Voiture.DATE_ACHAT).Value), Marque = voiture.Element(Voiture.MARQUE).Value, Poids = Convert.ToInt32(voiture.Element(Voiture.POIDS).Value), Prix = Convert.ToDouble(voiture.Element(Voiture.PRIX).Value) } ).ToList<Voiture>(); return lsVoiture; } #endregion
-
GetNewId
-
#region GetNewId /// <summary> /// Retourne le futur identifiant lors d'une création /// </summary> /// <param name="flux">Flux du fichier XML</param> /// <returns>Le nouvel identifiant</returns> private long GetNewId(string flux) { int nextId = 0; XDocument doc = XDocument.Load(flux); var voitures = from voiture in doc.Descendants(Voiture.VOITURE) orderby (int)voiture.Element(Voiture.ID) descending select new { newid = voiture.Element(Voiture.ID).Value, }; foreach (var voiture in voitures) { nextId = int.Parse(voiture.newid); break; } nextId++; return nextId; } #endregion
4. Ajouter la partie cliente, ici une page web
- Page default.aspx
<table> <tr> <td align="center"> <asp:Button runat="server" ID="btnGetAll" Text="Obtenir toutes les voitures" OnClick="btnGetAll_Click" /> </td> </tr> <tr> <td> Recherche par marque : <asp:TextBox runat="server" ID="txtSearchMarque"/> <asp:Button runat="server" ID="btnSearchMarque" Text="Rechercher" onclick="btnSearchMarque_Click"/> </td> </tr> <tr> <td> <asp:GridView runat="server" ID="gvVoitures" AutoGenerateColumns="false" OnRowCommand="gvVoitures_RowCommand"> <Columns> <asp:TemplateField> <ItemTemplate> <asp:Button runat="server" ID="btnEditVoiture" Text="Modifier" CommandName="UpdateCar" CommandArgument='<%# Eval("Id") %>' /> </ItemTemplate> </asp:TemplateField> <asp:TemplateField> <ItemTemplate> <asp:Button runat="server" ID="btnDeleteVoiture" Text="Supprimer" CommandName="DeleteCar" CommandArgument='<%# Eval("Id") %>' /> </ItemTemplate> </asp:TemplateField> <asp:BoundField DataField="Marque" HeaderText="Marque" /> <asp:BoundField DataField="Poids" HeaderText="Poids" /> <asp:BoundField DataField="DateAchat" HeaderText="Date d'achat" DataFormatString="{0:dd/MM/yyyy}" /> <asp:BoundField DataField="Prix" HeaderText="Prix" /> </Columns> </asp:GridView> </td> </tr> <tr> <td align="center"> <asp:Button runat="server" ID="btnAdd" Text="Ajouter une voiture" OnClick="btnAdd_Click" /> </td> </tr> </table> <asp:Panel runat="server" ID="pnlDetail" Visible="false" Width="600px"> <table> <tr> <td style="width: 150px" align="right"> Marque : </td> <td style="width: 450px"> <asp:TextBox runat="server" ID="txtMarque" Width="90%"/> </td> </tr> <tr> <td align="right"> Poids : </td> <td> <asp:TextBox runat="server" ID="txtPoids" Width="40%" /> </td> </tr> <tr> <td align="right"> Date d'achat : </td> <td> <asp:TextBox runat="server" ID="txtDateAchat" Width="40%" /> </td> </tr> <tr> <td align="right"> Prix : </td> <td> <asp:TextBox runat="server" ID="txtPrix" Width="40%" /> </td> </tr> <tr> <td colspan="2" align="center"> <asp:Button runat="server" ID="btnSave" Text="Valider" OnClick="btnSave_Click" /> </td> </tr> <tr> <td colspan="2" align="center"> <asp:Label runat="server" ID="lblErreur" ForeColor="Red"></asp:Label> </td> </tr> </table> </asp:Panel>
-
CodeBehind
- Déclaration des constantes
#region CONSTANTES /// <summary> /// Nom du fichier XML /// </summary> private const string XML_FILE = "XMLFile.xml"; /// <summary> /// Voiture en cours qui sera stockée dans un ViewState /// </summary> private const string VOITURE = "VOITURE"; /// <summary> /// Mode actuel (update ou insert) stocké dans un ViewState /// </summary> private const string MODE = "MODE"; /// <summary> /// Mode insert /// </summary> private const string INSERT = "INSERT"; /// <summary> /// Mode Update /// </summary> private const string UPDATE = "UPDATE"; #endregion
- Remplir la GridView
/// <summary> /// Remplir la grille des voitures /// </summary> private void FillGrid() { gvVoitures.DataSource = new VoitureService().GetAll(Server.MapPath(XML_FILE)); gvVoitures.DataBind(); }
- Méthode permettant d'afficher une voiture
/// <summary> /// Affichage d'une voiture dans le formulaire de détail /// </summary> private void AfficherVoiture() { Voiture voiture = (Voiture)ViewState[VOITURE]; txtMarque.Text = voiture.Marque; txtPrix.Text = voiture.Prix.ToString(); txtPoids.Text = voiture.Poids.ToString(); txtDateAchat.Text = voiture.DateAchat.ToString("dd/MM/yyyy"); }
- Méthode déclenchée lors de l'action sur la GridView
/// <summary> /// RowCommand sur la grille des voitures (modification ou suppression) /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected void gvVoitures_RowCommand(object sender, GridViewCommandEventArgs e) { switch (e.CommandName) { case "UpdateCar": ViewState[VOITURE] = new VoitureService().GetById(Convert.ToInt64(e.CommandArgument), Server.MapPath(XML_FILE)); AfficherVoiture(); pnlDetail.Visible = true; ViewState[MODE] = UPDATE; break; case "DeleteCar": Voiture voitureToDelete = new Voiture(); voitureToDelete.Id = Convert.ToInt64(e.CommandArgument); new VoitureService().Delete(voitureToDelete, Server.MapPath(XML_FILE)); FillGrid(); break; } }
- Action sur les boutons
#region BOUTONS /// <summary> /// Obtenir toutes les voitures /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected void btnGetAll_Click(object sender, EventArgs e) { FillGrid(); } /// <summary> /// Bouton de sauvegarde /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected void btnSave_Click(object sender, EventArgs e) { // Récupération du mode switch ((string)ViewState[MODE]) { // Insertion d'une nouvelle voiture case INSERT: Voiture voitureToInsert = new Voiture(); voitureToInsert.Marque = txtMarque.Text; voitureToInsert.DateAchat = Convert.ToDateTime(txtDateAchat.Text); voitureToInsert.Poids = Convert.ToInt32(txtPoids.Text); voitureToInsert.Prix = Convert.ToDouble(txtPrix.Text); new VoitureService().Insert(voitureToInsert, Server.MapPath(XML_FILE)); break; // Mise à jour de la voiture case UPDATE: try { // Récupération de la voiture actuelle dans le viewState Voiture voitureToUpdate = (Voiture)ViewState[VOITURE]; voitureToUpdate.Marque = txtMarque.Text; voitureToUpdate.DateAchat = Convert.ToDateTime(txtDateAchat.Text); voitureToUpdate.Poids = Convert.ToInt32(txtPoids.Text); voitureToUpdate.Prix = Convert.ToDouble(txtPrix.Text); new VoitureService().Update(voitureToUpdate, Server.MapPath(XML_FILE)); lblErreur.Text = string.Empty; } catch (FormatException) { lblErreur.Text = "Format des données incorrectes"; } break; } FillGrid(); } /// <summary> /// Bouton permettant d'ajouter une voiture /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected void btnAdd_Click(object sender, EventArgs e) { ViewState[MODE] = INSERT; pnlDetail.Visible = true; txtMarque.Text = string.Empty; txtPrix.Text = string.Empty; txtPoids.Text = string.Empty; txtDateAchat.Text = string.Empty; } /// <summary> /// Bouton de recherche par marque /// Renvoi une liste de voitures en fonction de la marque /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected void btnSearchMarque_Click(object sender, EventArgs e) { gvVoitures.DataSource = new VoitureService().GetByMarque(txtSearchMarque.Text.Trim().ToLower(), Server.MapPath(XML_FILE)); gvVoitures.DataBind(); } #endregion