خواندن از فایل XML

خواندن از فایل XML، تکنیکی لازم برای بدست آوردن اطلاعات از آن است. به عنوان مثال می‌توانید اطلاعات مربوط به پیکربندی برنامه را در یک فایل XML ذخیره کرده تا در اجراهای بعدی، برنامه با همان تنظیمات بارگذاری شود. در این درس قصد داریم به شما نحوه خواندن یک فایل XML را آموزش دهیم. یک برنامه ویندوزی مانند شکل زیر ایجاد کنید:
reading-xml-1001
نام چهار دکمه را به buttonFirst ،buttonPrevious ،buttonNext و buttonLast و نام جعبه‌های متن را به textBoxName ،textBoxAge و textBoxGender تغییر دهید. در این آموزش، نیاز به یک فایل XML داریم، که دارای رکوردهای باشد، که برنامه ما آنها را بخواند. از مسیری که در شکل زیر نشان داده شده است یک فایل XML ایجاد می‌کنیم :
reading-xml-1002

reading-xml-1002
نام فایل را sample.xml می‌گذاریم. محتویات آن را پاک و کدهای زیر را به جای آن‌ها می‌نویسیم:

<?xml version="1.0" encoding="utf-8" ?>
<Persons>
  <Person name="John Smith">
    <Age>30</Age>
    <Gender>Male</Gender>
  </Person>
  <Person name="Mike Folley">
    <Age>25</Age>
    <Gender>Male</Gender>
  </Person>
  <Person name="Lisa Carter">
    <Age>22</Age>
    <Gender>Female</Gender>
  </Person>
  <Person name="Jerry Frost">
    <Age>27</Age>
    <Gender>Male</Gender>
  </Person>
  <Person name="Adam Wong">
    <Age>35</Age>
    <Gender>Male</Gender>
  </Person>
</Persons>

این فایل شامل پنج رکورد Person است. برنامه خواندن فایل را از اولین Person شروع می کن. کاربر هم با زدن دکمه‌های پیمایش، می‌تواند بقیه رکوردها را مشاهده کند. به محیط کدنویسی رفته و فضای نام زیر را وارد می‌کنیم :

using System.Xml;

فیلدهای زیر را به کلاس form1 اضافه می‌کنیم :

private XmlDocument doc;
private XmlElement root;
private XmlElement currentPerson;
private const string PATH = @"..\..\sample.xml";
private int current = 0;
private int max;

doc برای بارگذاری و دستکاری فایل XML، متغیر root برای به دست آوردن عنصر ریشه و متغیر currentPerson برای نمایش عنصر Person جاری استفاده می‌شود. از مسیر “..\..\sample.xml” به این دلیل استفاده کرده‌ایم چون فایل XML در داخل دو پوشه تو در تو قرار دارد (به ازای هر پوشه دو نقطه (..) قرار داده‌ایم). متغیر current که با صفر مقدار دهی شده است برای نشان دادن اولین رکورد به کار می‌رود. متغیر max هم برای ذخیره بالاترین اندیس به کار می‌رود که برای برنامه مفید خواهد بود. حال به یک متد نیاز داریم که جزییات رکورد انتخاب شده را در جعبه‌های متن نمایش دهد. این متد را در داخل کلاس Form1 تعریف می‌کنیم:

private void ShowDetails(XmlElement currentPerson)
{
    textBoxName.Text = currentPerson.Attributes["name"].Value;
    textBoxAge.Text = currentPerson.GetElementsByTagName("Age")[0].InnerText;
    textBoxGender.Text = currentPerson.GetElementsByTagName("Gender")[0].InnerText;
}

متد ایجاد شده اطلاعات فرد انتخاب شده را می‌گیرد و مقدار صفت “name” را در جعبه متن مربوطه (textBoxName) نمایش می‌دهد. همانطور که مشاهده می‌کنید ما از خاصیت Attribute مربوط به کلاس XmlElement و یک رشته که نماینده نام صفت است استفاده کرده‌ایم و سپس با استفاده از خاصیت Value مقدار آن را به جعبه متن انتقال داده‌ایم. مقدار عنصر Age را به وسیله متد ()GetElementByTagName به دست می‌آوریم. ما نام عنصر را ارسال و متد همه عناصر فرزندی که با نام ارسال شده مطابقت دارند را به عنوان یک XmlNodeList (مجموعه‌ای از گره‌ها) بر می‌گرداند. از آنجاییکه XmlNodeList یک مجموعه است و ما فقط انتظار یک نتیجه را داریم بنابراین برای دسترسی به اولین عنصر می‌توانیم از اندیس صفر استفاده کنیم.

textBoxAge.Text = currentPerson.GetElementsByTagName("Age")[0].InnerText;

خط بالا برای افراد مبتدی کمی گیج کننده است. معنای این خط این است که اولین عنصر از مجموعه را بوسیله متد ()GetElementByTagName بگیر و با استفاده از خاصیت InnerText متن آن را به دست بیاور. کد بالا را به صورت چند خط زیر هم می‌توان نوشت :

XmlNodeList results = currentPerson.GetElementsByTagName("Age");
XmlNode first = results[0];
textBoxAge.Text = first.InnerText;

خط بعدی کد هم شبیه به کد بالا می‌باشد با این تفاوت که عنصر Gender (جنسیت) به وسیله متد ()GetElementsByTagName بر گشت داده می‌شود. با تکمیل متد، نوبت به ایجاد کنترل کننده رویداد می‌رسد. به محیط طراحی می‌رویم و بر روی فضای خالی از فرم کلیک می‌کنیم تا کنترل کننده رویداد Load ایجاد شود، سپس کد زیر را به آن اضافه می‌کنیم :

private void Form1_Load(object sender, EventArgs e)
{
    doc = new XmlDocument();
    doc.Load(PATH);

    //Get root element
    root = doc.DocumentElement;

    //Determine maximum possible index
    max = root.GetElementsByTagName("Person").Count - 1;

    //Get the record at the current index
    currentPerson = (XmlElement)root.ChildNodes[current];

    //Show the record information
    ShowDetails(currentPerson);
}

این کد بعد از بارگذاری فرم اجرا می‌شود و اولین رکورد را بازیابی و نمایش می‌دهد. ابتدا یک شئ XmlDocument ایجاد می‌کنیم. سپس فایل XML را که در مسیری که در متغیر PATH مشخص شده است را با استفاده از متد Load کلاس XmlDocument بارگذاری می‌کنیم. عنصر ریشه را به وسیله خاصیت DocumentElement و سپس بالاترین اندیس ممکن را با استفاده شمارش عناصر فرزند به دست می‌آوریم. همانطور که مشاهده می‌کنید ما تعداد عنا صر فرزند را منهای عدد یک کرده‌ایم چون اندیس‌ها از صفر شروع می‌شوند. برای به دست آوردن اولین شخص مقدار صفر را به عنوان اندیس به متد ChildNodes ارسال می‌کنیم.
خاصیت ChildNodes مجموعه‌ای همه گره‌های فرزند یک گره است و با ارسال عدد صفر به عنوان اندیس، می‌توانیم اولین رکورد را بدست بیاوریم. از آنجاییکه ChildNodes عبارت است از اشیاء XmlNode لازم است که گره را تبدیل به XmlElement کرده و آن را در شئ XmlElement ذخیره کنیم. البته این کار را می‌توان با استفاده از متد GetElementsByTagName نیز انجام داد و دلیل استفاده از متد ChildNodes نشان دادن روشی جایگزین است. حال عنصر به دست آمده را به متدی که از قبل ساخته‌ایم ارسال می‌کنیم. با ارسال عنصر به متد، جزییات عنصر person جاری بدست می‌آید. به محیط طراحی برگشته و بر روی buttonFirst دوبار کلیک می‌کنیم و کد زیر را در کنترل کننده رویداد آن می‌نویسیم :

private void buttonFirst_Click(object sender, EventArgs e)
{
    current = 0;
    currentPerson = (XmlElement)root.ChildNodes[current];
    ShowDetails(currentPerson);
}

خط اول اندیس جاری را صفر می‌کند و درنتیجه گره فرزند با اندیس صفر به دست می‌آید. سپس با استفاده از متد ShowDetails جزییات آن را به دست می‌آوریم. حال اجازه دهید که به کنترل کننده رویداد کلیک دکمه buttonPrevious نگاهی بیندازیم:

private void buttonPrevious_Click(object sender, EventArgs e) 
{ 
     current = (current - 1 < 0) ? 0 : current - 1; 
     currentPerson = (XmlElement)root.ChildNodes[current]; 
     ShowDetails(currentPerson); 
}

کد بالا به جز در خط اول شبیه به کنترل کننده رویداد دکمه buttonFirst می‌باشد. برای به دست آوردن عنصر قبلی به سادگی از عبارت (current – 1) استفاده می‌کنیم. در خط اول چک می‌کنیم که آیا عنصر قبلی کوچکتر از صفر است یا نه؟ اگرکوچکتر بود، ما مقدار صفر را در نظر می‌گیریم چون مقدار صفر اولین عنصر را نشان می‌دهد (عنصر اول دارای اندیس صفر است و اندیس منفی معنا ندارد).
این کار از وقوع استثناء (IndexOutOfRangeException) جلوگیری می‌کند. اگر کاربر بر روی اولین رکورد باشد، کلیک بر روی دکمه buttonPrevious بی تأثیر خواهد بود. اگر اندیس بزرگتر یا مساوی صفر بود عبارت current – 1 اولین عنصر یا عنصر قبلی را نشان خواهد داد و در نهایت عنصر با اندیس جدید برگشت و جزییات آن با استفاده از متد ShowDetails نمایش داده می‌شود. حال اجازه دهید به کدهای دکمه buttonNext که مسئول نمایش رکورد بعدی است نگاهی بیندازیم :

private void buttonNext_Click(object sender, EventArgs e)
{
    current = (current + 1 > max) ? max : current + 1;
    currentPerson = (XmlElement)root.ChildNodes[current];
    ShowDetails(currentPerson);
}

تنها تفاوت در به دست آوردن عنصر قبل و عنصر بعد در بدست آوردن اندیس عنصر جدید است. رکورد بعدی با استفاده از عبارت (current + 1) به دست می‌آید. همانطور که در کد بالا مشاهده می‌کنید ما با استفاده از یک دستور شرطی چک کرده‌ایم که آیا مقدار این عبارت از نهایت مقدار اندیس‌ها که در متغیر max ذخیره شده است بیشتر است یا نه؟ اگر بیشتر بود به راحتری مقدار max را برابر این عبارت قرار می‌دهیم و اگر مساوی یا کوچکتر از متغیر max بود در اینصورت عنصر بعدی با همین عبارت (current + 1) نمایش داده می‌شود. و در آخر بر روی دکمه buttonLast دو بار کلیک کرده و کنترل کننده رویداد زیر را به آن اضافه کنید :

private void buttonLast_Click(object sender, EventArgs e)
{
    current = max;
    currentPerson = (XmlElement)root.ChildNodes[current];
    ShowDetails(currentPerson);
}

از آنجاییکه به دست آوردن آخرین رکورد مد نظر ماست، از مقدار max (که همان تعداد عناصر است) به جای اندیس استفاده می‌کنیم. برنامه را اجرا کنید تا داده‌های اولین رکورد برای شما نمایش داده شود و سپس با کلیک بر روی دکمه‌ها در بین رکوردهای فایل XML حرکت کنید. شما اکنون یک برنامه ایجاد کرده‌اید که رکوردهای موجود در یک فایل XML را با استفاده از کلاس‌های XML DOM می‌خواند.