Kolekcja obiektów i plik XML – zapis, odczyt i modyfikacja danych przy użyciu LINQ to XML

2012-05-18

Na platformie .NET od wersji 3.5 dostępna jest technologia LINQ oferująca uniwersalny mechanizm zadawania zapytań do obiektów. W tym wpisie pokażę w jaki sposób przy użyciu LINQ to XML przenieść dane z kolekcji obiektów do dokumentu XML, wczytać dane z pliku XML do kolekcji oraz zmodyfikować zawartość XML-a. Posłużę się w tym celu klasą System.Xml.Linq.XDocument.

Załóżmy, że mamy klasę Osoba o następującej strukturze:

class Osoba
{
    public string Pesel { get; set; }
    public string Imie { get; set; }
    public string Nazwisko { get; set; }
    public int Wzrost { get; set; }

    public Osoba(string pesel, string imie, string nazwisko, int wzrost)
    {
        Pesel = pesel;
        Imie = imie;
        Nazwisko = nazwisko;
        Wzrost = wzrost;
    }
}

Poniższy kod tworzy kolekcję trzech obiektów typu Osoba, po czym dane z tej kolekcji (posortowane po nazwisku i imieniu) przenosi do dokumentu XML. Na końcu dokument zapisywany jest do pliku Osoby.xml:

List<Osoba> listaOsob = new List<Osoba>();
listaOsob.Add(new Osoba("70010123456", "Jan", "Kowalski", 180));
listaOsob.Add(new Osoba("75061598765", "Janina", "Kowalska", 160));
listaOsob.Add(new Osoba("80122012398", "Marian", "Kowalski", 185));

XDocument xml = new XDocument(
    new XDeclaration("1.0", "utf-8", "yes"),
    new XComment("Lista osób z kolekcji"),
    new XElement("osoby",
        from osoba in listaOsob
        orderby osoba.Nazwisko, osoba.Imie
        select new XElement("osoba",
            new XAttribute("pesel", osoba.Pesel),
            new XElement("imie", osoba.Imie),
            new XElement("nazwisko", osoba.Nazwisko),
            new XElement("wzrost", osoba.Wzrost)
            )
        )
    );

xml.Save("Osoby.xml");

Zawartość utworzonego pliku XML:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<!--Lista osób z kolekcji-->
<osoby>
  <osoba pesel="75061598765">
    <imie>Janina</imie>
    <nazwisko>Kowalska</nazwisko>
    <wzrost>160</wzrost>
  </osoba>
  <osoba pesel="70010123456">
    <imie>Jan</imie>
    <nazwisko>Kowalski</nazwisko>
    <wzrost>180</wzrost>
  </osoba>
  <osoba pesel="80122012398">
    <imie>Marian</imie>
    <nazwisko>Kowalski</nazwisko>
    <wzrost>185</wzrost>
  </osoba>
</osoby>

Jeżeli mamy plik XML, możemy na podstawie jego zawartości utworzyć kolekcję obiektów typu Osoba:

XDocument xml = XDocument.Load("Osoby.xml");

List<Osoba> listaOsob = (
    from osoba in xml.Root.Elements("osoba")
    select new Osoba(
        osoba.Attribute("pesel").Value,
        osoba.Element("imie").Value,
        osoba.Element("nazwisko").Value,
        int.Parse(osoba.Element("wzrost").Value)
        )
    ).ToList<Osoba>();

Ostatnią operacją jest modyfikacja danych w istniejącym pliku XML. Pokażę dwa sposoby jej realizacji. Załóżmy, że osobie o numerze pesel 75061598765 chcemy zmienić nazwisko na Nowak.

Przykład 1:

XDocument xml = XDocument.Load("Osoby.xml");

var osoby = xml.Root.Elements("osoba").Where(
    osoba => osoba.Attribute("pesel").Value == "75061598765");
if (osoby.Any())
    osoby.First().Element("nazwisko").Value = "Nowak";

xml.Save("Osoby.xml");

Przykład 2:

XDocument xml = XDocument.Load("Osoby.xml");

var osoby = from osoba in xml.Root.Elements("osoba")
            where osoba.Attribute("pesel").Value == "75061598765"
            select osoba;
if (osoby.Any())
    osoby.First().Element("nazwisko").Value = "Nowak";

xml.Save("Osoby.xml");

W obu przykładach w pliku XML zmodyfikowane zostało nazwisko odpowiedniej osoby:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<!--Lista osób z kolekcji-->
<osoby>
  <osoba pesel="75061598765">
    <imie>Janina</imie>
    <nazwisko>Nowak</nazwisko>
    <wzrost>160</wzrost>
  </osoba>
  <osoba pesel="70010123456">
    <imie>Jan</imie>
    <nazwisko>Kowalski</nazwisko>
    <wzrost>180</wzrost>
  </osoba>
  <osoba pesel="80122012398">
    <imie>Marian</imie>
    <nazwisko>Kowalski</nazwisko>
    <wzrost>185</wzrost>
  </osoba>
</osoby>

W przypadku zapytań na dokumentach XML, do kolekcji ich elementów mamy dostęp poprzez odpowiednie właściwości i metody:

  • Root – element główny wraz z całą zawartością dokumentu
  • Elements – elementy-dzieci bieżącego elementu z możliwością podania ich nazwy
  • Nodes – węzły-dzieci bieżącego elementu (w odróżnieniu od Elements zwracane są także komentarze i tekst)
  • Descendants – elementy-dzieci bieżącego elementu na dowolnym poziomie z możliwością podania ich nazwy
  • Parent – rodzic bieżącego elementu
  • Ancestors – rodzice bieżącego elementu na dowolnym poziomie z możliwością podania ich nazwy
  • ElementsBeforeSelf – elementy o tym samym rodzicu znajdujące się przed bieżącym elementem z możliwością podania ich nazwy
  • ElementsAfterSelf – elementy o tym samym rodzicu znajdujące się po bieżącym elemencie z możliwością podania ich nazwy
  • Attributes – atrybuty bieżącego elementu z możliwością podania ich nazwy

Więcej informacji o technologii LINQ to XML: MSDN

Reklamy

Posted on 2012-05-18, in .NET/C# and tagged , , , , . Bookmark the permalink. 4 Komentarze.

  1. INSERT, UPDATE, DELETE oraz JOIN zaprezentowałem tutaj: http://kurzyniec.pl/artykuly/xlinq

    Dodatkowo – zamiast Count() zdecydowanie wydajniej jest korzystać z Any().

  1. Pingback: Notatki deweloperskie « Wiadomości o technologiach IT

  2. Pingback: Podsumowanie 2012 « Developer notes

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Wyloguj / Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Wyloguj / Zmień )

Zdjęcie na Facebooku

Komentujesz korzystając z konta Facebook. Wyloguj / Zmień )

Zdjęcie na Google+

Komentujesz korzystając z konta Google+. Wyloguj / Zmień )

Connecting to %s

%d blogerów lubi to: