CodeGym /Kurslar /C# SELF /XML ilə qabaqcıl iş: XmlDo...

XML ilə qabaqcıl iş: XmlDocumentXPath

C# SELF
Səviyyə , Dərs
Mövcuddur

1. Giriş

Bir SOAP‑servis və ya bank API-si sizə nəhəng XML göndərdiyini təsəvvür edin. İçində yüzlərlə bükülmüş element, qeyri‑homo­gen struktur var və sizdən tələb olunur keçən ayın yalnız bir ödəniş məbləğini tapmaq. Serializasiya yanaşması burada uyğun gəlmir — çox köhnə‑tip və əvvəlcədən haraya baxılacağını bilmirsiniz. XML‑də "böyüdücü" və ağacda sürətlə hərəkət etməyi bacarmaq lazımdır.

Məhz belə hallar üçün .NET‑də uzun illərdir güclü vasitə var — XmlDocument sinfi və ona əlavə olaraq sorğu dili XPath. Bu gün öyrənəcəksiniz:

  • XML‑i DOM‑a yükləmək;
  • Əllə və XPath ilə lazım olan elementlərə hərəkət etmək və tapmaq;
  • XML sənədinin məzmununu modifikasiya etmək;
  • Element və atribut əlavə etmək, silmək və dəyişmək;
  • Çətin seçkilər üçün XPath istifadə etmək.

2. XmlDocument nədir?

XmlDocumentSystem.Xml namespace‑indən olan sinifdir. Bu, Document Object Model‑in (DOM) — bütün XML faylını yaddaşda obyektlər ağacı kimi təqdim edən realizasiyasıdır.

Bir az nəzəriyyə və analoqlar

Əgər XmlSerializer LEGO konstruktora oxşayırsa — obyektinizi kubiklərə çevirirsiniz və geri, onda XmlDocument həqiqi bir ağacla işləməyə bənzəyir: kök, budaqlar (elementlər), yarpaqlar (text node‑lar) var və siz bu ağacda gəzə, budaqlar əlavə edə, yarpaqları kəsib başqa yerə köçürə bilərsiniz.

XML sənədinin sadə yüklənməsi

Tutaq ki, bizim belə bir XML‑imiz var:

<users>
  <user id="1">
    <name>Olga</name>
    <age>28</age>
  </user>
  <user id="2">
    <name>Igor</name>
    <age>35</age>
  </user>
</users>

Bunu yaddaşa yükləyək:

using System.Xml;

string xml = @"
<users>
  <user id='1'>
    <name>Olga</name>
    <age>28</age>
  </user>
  <user id='2'>
    <name>Igor</name>
    <age>35</age>
  </user>
</users>";

XmlDocument doc = new XmlDocument();
doc.LoadXml(xml); // veya doc.Load("fayl_yolu.xml");

LoadXml (və ya fayldandırsa Load) çağırdıqdan sonra sənədin məzmununa tam girişiniz olur.

3. DOM‑a naviqasiya

DOM ağacının strukturu

Hər XML sənədi yükləndikdən sonra müxtəlif tiplərdə node‑lardan ibarət bir ağaca çevrilir:

Node tipi .NET sinfi Nümunə
Document XmlDocument
<users>...</users>
Element XmlElement
<user>, <name>
Attribute XmlAttribute
id="1"
Text XmlText Olga, 28
Comment XmlComment
<!-- şərh -->

Lazım olan elementlərə müraciət etmək üçün ChildNodes, Attributes, ParentNode və s. kimi property‑lərdən "ağac boyunca gəzərək" istifadə etməlisiniz.

Kök elementi əldə edirik

XmlElement root = doc.DocumentElement;
Console.WriteLine(root.Name); // users

Uşaq elementləri ilə dövr

foreach (XmlNode node in root.ChildNodes)
{
    if (node is XmlElement user)
    {
        // user — <user id="...">...</user>
        string id = user.GetAttribute("id");
        string name = user["name"].InnerText;
        string age = user["age"].InnerText;
        Console.WriteLine($"Istifadəçi {id}: {name}, yaş {age}");
    }
}

VACIB: user["name"] yalnız birbaşa child olaraq <name> varsa işləyir.

Atributlara və mətinə giriş

var firstUser = root.FirstChild as XmlElement;
string id = firstUser.GetAttribute("id"); // "1"
string name = firstUser["name"].InnerText; // "Olga"

4. XML sənədinin modifikasiyası

Dəyərin dəyişdirilməsi

Tutaq ki, Olga birdən "gəncləşmək" qərarına gəldi:

var olga = root.FirstChild as XmlElement;
olga["age"].InnerText = "22"; // indi <age>22</age>

Yeni istifadəçi əlavə etmək

XmlElement newUser = doc.CreateElement("user");
newUser.SetAttribute("id", "3");

XmlElement name = doc.CreateElement("name");
name.InnerText = "Vasilisa";
XmlElement age = doc.CreateElement("age");
age.InnerText = "19";

newUser.AppendChild(name);
newUser.AppendChild(age);
root.AppendChild(newUser);

Elementi silmək

İkinci istifadəçini ("Igor") silək:

XmlNode userToDelete = root.SelectSingleNode("user[@id='2']");
if (userToDelete != null)
    root.RemoveChild(userToDelete);

Dəyişiklikləri saxlamaq

doc.Save("users_updated.xml");
// Və ya doc.OuterXml — XML sətiri almaq üçün

5. XPath — XML-də axtarış və seçmə dili

Əgər DOM ağacı ilə işləmək yorucu olur, çünki şərtə görə element tapmaq lazımdırsa — məsələn, bütün 25‑dən yuxarı istifadəçilər. Bunun üçün XPath var — XML ağacı üzrə naviqasiya dilidir.

XPath-in əsas istifadəsi

XPath sorğularını SelectSingleNode (ilk tapılan node‑u qaytarır) və SelectNodes (node kolleksiyası qaytarır) vasitəsilə icra etmək olar.

Nümunə: id = 1 olan istifadəçini tapmaq

XmlNode user = root.SelectSingleNode("user[@id='1']");
Console.WriteLine(user["name"].InnerText); // Olga

Nümunə: 25‑dən böyük bütün istifadəçiləri tapmaq

XmlNodeList nodes = root.SelectNodes("user[age>25]");
foreach (XmlNode u in nodes)
{
    Console.WriteLine(u["name"].InnerText); // Olga və Igor (əgər Igor hələ silinməyibsə)
}

XPath — qısa sintaksis

XPath ifadəsi Nə edəcək
/users/user
root <users> içindəki bütün <user> elementləri
user[@id='3']
id=3 olan istifadəçi
user[age>25]
25‑dən böyük istifadəçilər
user/name
Bütün istifadəçilərin bütün <name> elementləri
user[last()]
Son <user>
user[position()<3]
ilk iki <user>

Daha çox nümunə və sintaksis: XPath sənədləşməsi.

Başqa bir nümunə: nested elementlərə görə seçmə

Tutaq ki, XML daha mürəkkəbdir:

<library>
  <book>
    <title>Lord of the Flies</title>
    <author>
      <firstname>William</firstname>
      <lastname>Golding</lastname>
    </author>
  </book>
  <book>
    <title>In Search of Lost Time</title>
    <author>
      <firstname>Marcel</firstname>
      <lastname>Proust</lastname>
    </author>
  </book>
</library>
XmlDocument doc = new XmlDocument();
doc.LoadXml(libraryXml);
XmlNodeList authors = doc.SelectNodes("/library/book/author/lastname");
foreach (XmlNode lastName in authors)
    Console.WriteLine(lastName.InnerText);

Nə çap olunacaq:

Golding
Proust

6. XPath: filtrasiya, məntiq, hesablamalar

Məntiqi filtrlər

Yaşı 1830 arasında olan bütün istifadəçilərin adlarını çıxarmaq:

// [age>=18 and age<=30]
XmlNodeList youngUsers = root.SelectNodes("user[age>=18 and age<=30]");
foreach (XmlNode u in youngUsers)
    Console.WriteLine(u["name"].InnerText);

Atributlarla işləmək

Atributlar @ ilə seçilir. id‑si "1" ilə başlayan istifadəçiləri tapmaq:

XmlNodeList nodes = root.SelectNodes("user[starts-with(@id, '1')]");

Node sayını saymaq

C#‑da birbaşa SelectNodes metodunda count() funksiyasını istifadə edə bilməzsiniz — o, kolleksiya qaytarır, ədəd yox. Amma belə edə bilərsiniz:

int count = root.SelectNodes("user").Count;

Nested filtrlər

XmlNodeList nodes = doc.SelectNodes("/library/book[author/lastname='Golding']");

7. XPath və namespace‑lər

Əgər XML‑də namespace (xmlns) istifadə olunubsa, iş bir az daha maraqlı olur. Belə hallarda XmlNamespaceManager istifadə edin:

<catalog xmlns="http://books.example.com">
  <book>
    <title>Algorithms</title>
  </book>
</catalog>
doc.LoadXml(xml);
XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("b", "http://books.example.com");

XmlNodeList books = doc.SelectNodes("/b:catalog/b:book", nsmgr);
foreach (XmlNode book in books)
    Console.WriteLine(book.SelectSingleNode("b:title", nsmgr)?.InnerText);

8. DOM vasitəsilə XML modifikasiyası

"Canlı" node əlavə etmək

Birinci istifadəçiyə yeni <email> elementi əlavə edək:

XmlElement email = doc.CreateElement("email");
email.InnerText = "olga@gmail.com";
olga.AppendChild(email);

Atributları dəyişdirmək

olga.SetAttribute("id", "99"); // İndi id="99"

XPath ilə node‑ları silmək

XmlNodeList nodesToRemove = root.SelectNodes("user[age<20]");
foreach (XmlNode node in nodesToRemove)
    root.RemoveChild(node);

9. Faydalı nüanslar

Axtarış və kütləvi struktur dəyişdirmə

Tutaq ki, sizə böyük XML gəlir və orada müxtəlif <record type="..."> elementləri var. Yalnız atributu type‑i "customer" olanları saxlamaq və hər birinə child olaraq <status>active</status> əlavə etmək lazımdır.

XmlNodeList customerNodes = root.SelectNodes("record[@type='customer']");
foreach (XmlElement record in customerNodes)
{
    XmlElement status = doc.CreateElement("status");
    status.InnerText = "active";
    record.AppendChild(status);
}

XML node ağacı (DOM)


users
├─ user (id="1")
│   ├─ name ("Olga")
│   └─ age ("28")
├─ user (id="2")
│   ├─ name ("Igor")
│   └─ age ("35")

XPath üzrə seçim nümunəsi

XPath‑sorgu Nə qaytaracaq
/users/user[1]
Birinci istifadəçi (id="1")
/users/user[last()]
Son istifadəçi (id="2")
/users/user[age>30]
30‑dan böyük olanlar (Igor)
/users/user[@id='2']
id="2" olan istifadəçi

Praktik tətbiq

  • Köhnə API‑lərlə integrasiyalar. Bir çox dövlət şirkətində və bankda SOAP/XML hələ də geniş istifadə olunur. Böyük XML cavabında nəyisə sürətlə tapıb dəyişmək onlarla saatı xilas edə bilər.
  • Məlumatların miqrasiyası. Bir sistemdən digərinə keçərkən çox vaxt XML parse edib çətin seçkilər, transformasiyalar və kütləvi dəyişikliklər etmək lazım gəlir.
  • Excel‑ə import‑export. Bir çox B2B məhsuluna hələ də XML daxil olur. Orada XPath — böyük data modeli yaratmadan lazım olanı əldə etməyin sürətli yoludur.

10. Səhvlər, nüanslar və tipik tələlər

NullReferenceException: Məsələn, mövcud olmayan elementə müraciət etsəniz — el["something"].InnerText — və belə child yoxdursa, xəta alacaqsınız. Həmişə null üçün yoxlayın.

XPath və nesting: Unutmayın ki, ifadə başlanğıc / olmadan cari node‑un potomları arasında axtarır, / ilə isə sənədin kökündən başlayır. Müxtəlif start nöqtələri nəticə olmamasına gətirə bilər, baxmayaraq ki, data mövcuddur.

Namespace ilə işləmək: Əgər XmlNamespaceManager istifadə etməsəniz, XPath sorğuları xmlns olan XML‑lərdə boş qaytara bilər.

İterasiya zamanı modifikasiya: SelectNodes nəticəsinə əsasən node‑ları silmək istəyirsinizsə, əvvəlcə onları massivə yığın, sonra iterasiya edin — yoxsa kolleksiya iterasiya zamanı dəyişər və səhvlər yaranar.

Text və element node‑larının fərqi: Elementlər arasında boşluq və line‑break kimi text node‑lar ola bilər. Sərt seçim üçün yalnız XmlElement istifadə edin və ya NodeType ilə filtr tətbiq edin.

2
Tapşırıq
C# SELF, səviyyə, dərs
Bağlanıb
XPath ilə elementlərin axtarışı
XPath ilə elementlərin axtarışı
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION