15
مارس

معالجة XML في PHP

أحدثت XML انقلاباً كبيراً عند صدورها لأول مرة في العام 1998 عندما أصبحت أحد معايير مؤسسة w3c.

بعد صدورها انبثقت لغات عديدة من XML واستخدمت في أنواع مختلفة من المجالات، كالجرافيك SVG والوسائط المتعددة SMIL والرياضيات MathML وحتى WSDL لـ (خدمات الويب Web Services).

في هذه المقالة سأستعرض كيفية “معالجة” ملفات XML من خلال لغة PHP.

ما هي XML؟

في هذا المقالة سأتطرق إلى طريقة معالجة ملفات XML بواسطة PHP فقط. وإذا كنت تريد معرفة المزيد عن XML فإليك هذا الرابط: http://www.w3c.org.ma/XML/XML-in-10-points.ar.html

طرق المعالجة المتوفرة

هناك ثلاث طرق متاحة في PHP لمعالجة ملفات XML وهي:

  • SAX أو SimpleAPI for XML.
  • DOM أو Document Object Modal.
  • SimpleXML.

هذه الطرق متوفرة كإضافات (Extensions) مكتوبة بلغة C في PHP باستثناء SimpleXML والتي تأتي مضمّنة مع PHP (الإصدار 5 فما فوق).

ملف XML المستخدم

سأستخدم في هذه المقالة ملف XML يحتوي على قائمة ببعض “الأكلات العراقية” أضغط هنا لتحميل الملف.

1) معالجة ملف XML بواسطة SAX

SAX أو (Simple API for XML) عبارة عن طريقة لمعالجة ملفات XML وتعتبر بديلاً جيداً (في بعض الأحيان) عن DOM.

يقوم معالج SAX بقراءة محتويات ملف XML بشكل متتابع (Sequential access) ويطلق أحداث (Events) لكل وسم (Tag) مفتوح (Open) ومغلق (Close). ولأي عنصر آخر في ملف XML.

معنى ذلك أنه يمكننا الوصول إلى أي وسم (Tag) نريده بهذه الطريقة، لأن SAX سيتتبع جميع الوسوم في ملف XML ويشخصها.

ولمعرفة ما هو “الوصول المتتابع” إليك التعريف التالي مع صورة توضيحية من موسوعة ويكيبيديا:

في علم الحاسوب ، الوصول المتتابع (بالإنجليزية: Sequential access) و هي طريقة الدخول إلى مجموعة من العناصر محددة سلفاً بطريقة تتبع خطوات متتالية أو مرتبة ، أي بطريقة متتابعة تعتمد على أخر وصول للبيانات.

بعد أن عرفنا طريقة عمل SAX نأتي الآن إلى مثال “بسيط” يعالج ملف XML لقائمة الطعام.

1
2
3
$xml = xml_parser_create('UTF-8');
xml_set_element_handler($xml, 'startHandler', 'endHandler');
xml_set_character_data_handler($xml, 'charHandler');

في السطر:

  • الأول: قمنا بإنشاء “مقبس” (Handle) بترميز UTF-8 سنستخدمه لمعالجة ملف XML.
  • الثاني: يقوم بتعريف الدوال التي ستقوم بمعالجة ملف XML. قمنا هنا بتعريف دالة startHandler لتشخيص عنصر (Tag) المفتوح. ودالة endHandler لتشخيص العنصر المغلق.
  • الثالث: دالة charHandler لتشخيص بيانات العنصر.

الدوال أعلاه تقوم بتنظيم “المقابس” (Handlers) للـ SAX لاستخدامها في معالجة ملف XML.

نأتي الآن إلى تعريف الدوال التي قمنا بتعريفها أعلاه.

startHandler

تقوم هذه الدالة بتشخيص الوسم المفتوح (Open Tag) وتأخذ ثلاث باراميترات:

  • مقبس XML.
  • اسم الوسم (Tag Name).
  • مصفوفة تحتوي على السمات (Attributes) الخاصة بالعنصر.

endHandler

تقوم هذه الدالة بتشخيص العنصر المغلق (Close Tag) وتأخذ الباراميترات التالية:

  • مقبس XML.
  • اسم الوسم (Tag Name).

charHandler

تقوم هذه الدالة بتشخيص “بيانات الوسم” (Tag Data) وتأخذ البارميترات التالية:

  • مقبس XML.
  • بيانات الوسم (Tag Data).

مثال باستخدام SAX

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
$xml = xml_parser_create('UTF-8');
 
xml_set_element_handler($xml, 'startHandler', 'endHandler');
xml_set_character_data_handler($xml, 'charHandler');
xml_parse($xml, file_get_contents('iraqiFood.xml') );
 
function startHandler($xml, $tag, $attr)
{
foreach ($attr as $k => $v)
{
$setAttr = $k .' = '.$v;
}
 
$setAttr = (!empty($setAttr))? '('.$setAttr.')':'(No attr)';
 
echo 'Start at: <strong>'.$tag.'</strong>; Attributes: '.$setAttr;
}
 
function endHandler($xml, $tag)
{
echo 'End at: <strong>'.$tag.'</strong>
 
 ';
}
 
function charHandler($xml, $data)
{
echo ' <span style="color: red; text-decoration: underline;">'.$data.'</span> ';
}

أعتقد أن المثال واضح جداً، كل ما عليك هو تعريف المقبس ثم الدوال، ثم استخدام الدالة xml_parse لمعالجة الملف.

يمكنك باستخدام الدالة xml_parser_set_option تحديد بعض الخيارات في معالجة الملف كـ: XML_OPTION_CASE_FOLDING لحساسية الأحرف للوسوم، false بمعنى غير حساسة لحالة الأحرف.

لقد قمت بتوضيح كيفية استخدام SAX ويمكنك كتابة شيفرة لمعالجة ملف XML كما ترغب.

معالجة ملف XML بواسطة DOM

إن معالجة ملف XML أو حتى XHTML بواسطة SAX Parser سيأخذ الكثير من الوقت.

المعالجة باستخدام DOM هي أبسط بكثير من SAX ولكن لها ثمنها وهو “الذاكرة” (Memory).

لا تعد الذاكرة ذات أهمية في ملفات XML ذات الحجم البسيط (كمثالنا). لكن عند معالجة ملف بحجم 20 ميجا بايت باستخدام DOM سيظهر لنا الفارق بوضوح.

بدلاً من قراءة الملف بالكامل (طريقة SAX) وإطلاق حوادث (Events) لكل عنصر، يقوم DOM برسم شجرة لعناصر (Elements) ملف XML تعتمد على “الأب” (Parent) و”الابن” (Child) مثال:


لمزيد من المعلومات عن DOM أو (Document Object Modal) أنظر: http://en.wikipedia.org/wiki/Document_Object_Model

أمثلة عن استخدام DOM:

نقوم أولاً بإنشاء مقبس لـ DOM كما يلي:

1
2
3
$dom    =    new DOMDocument();
$dom->load('iraqiFood.xml');
$root    =    $dom->documentElement;

documentElement يعني “العنصر الرئيسي” الذي تتفرع منه العناصر الأخرى. سنستخدم هذا العنصر للوصول إلى أبناءه (Children).

المثال الأول: قراءة العناصر

1
2
3
4
5
foreach ( $root->childNodes AS $item )
{
print $item->nodeName . " = " . $item->nodeValue . "
";
}
  • nodeName :: اسم الوسم (Tag Name).
  • nodeValue :: قيمة الوسم (Tag Value).

استخراج “صفة” Attribute

1
2
$root    =    $dom->documentElement->getElementsByTagName('food')->item(0);
echo $root->getAttributeNode('time')->value;
  • getElementsByTagName :: استخراج العنصر حسب الاسم.
  • getAttributeNode :: استخراج الصفة Attribute.

المثال الثاني: استخراج قائمة الطعام العراقية.

في هذا المثال سنقوم باستخراج قائمة الأطعمة العراقية وترتيبها.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$root = $dom->getElementsByTagName('food');
foreach ($root as $food)
{
echo '
<h1>'.$food->getElementsByTagName('name')->item(0)->nodeValue.'</h1>
';
echo '
 
<hr />
 
';
echo $food->getElementsByTagName('description')->item(0)->nodeValue;
echo '<img src="'.$food->getElementsByTagName('img')->item(0)->nodeValue.'" alt="" />';
}

استخدام XPath في DOM

XPath عبارة عن “لغة استعلام” (Query Language) تستخدم للاستعلام عن “عناصر” (Nodes) في لغة XML.

XPath تستخدم أيضاً في XSLT لتطابق “Match” العناصر (Nodes).

XPath أشبه ما يكون بلغة SQL للاستعلام من قواعد البيانات.

مثال حول استخدام XPath:

 

1
2
3
4
5
$dom    =    new DOMDocument();
$dom->load('iraqiFood.xml');
$xpath    =    new DOMXPath($dom);
$nodes    =    $xpath->query('*[local-name()="food"]', $dom->documentElement);
echo $nodes->item(0)->nodeValue;

إنشاء “شجرة عناصر” باستخدام DOM

يمكن إنشاء مستند XML بواسطة DOM باستخدام الطرق التالية:

  • createElement :: إنشاء عنصر.
  • setAttribute :: إنشاء صفة للعنصر.
  • createNodeText :: إضافة نص إلى العنصر.
  • appendChild :: إلحاق العنصر (حفظ العنصر).

مثال:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$dom    =    new DOMDocument();
$dom->formatOutput = true;
 
$html     = $dom->createElement('html');
$html->setAttribute('xmlns', 'http://www.w3.org/1999/xhtml');
$html->setAttribute('xml:lang', 'en');
$html->setAttribute('lang', 'en');
$dom->appendChild($html);
 
$head     = $dom->createElement('head');
$dom->appendChild($head);
 
$title     = $dom->createElement('title');
$title->appendChild($dom->createTextNode("XML Example"));
$dom->appendChild($title);
 
echo $dom->saveHTML();

يمكنك استخدام saveXML بدلاً من saveHTML لحفظ الملف كـ XML.

معالجة XML بواسطة SimpleXML

بعد أن تطرّقنا إلى SAX و DOM نأتي الآن إلى شرح آخر طريقة وهي SimpleXML.

SimpleXML هي أسهل طريقة لمعالجة ملفّات XML في PHP فهي تأتي مضمّنة مع PHP. ليس ضرورياً أن تعرف هيكلية DOM. يمكنك الوصول إلى العناصر بواسطة هيكيلية ملف XML نفسه.

يمكن إنشاء SimpleXML بواسطة أحد الطرق التالية:

 

1
2
$sxLoadFile     = simplexml_load_file('iraqiFood.xml');
$sxLoadString    = simplexml_load_string($XMLstring);

يمكن أيضاً استخدام DOM كما يلي:

 

1
2
3
$dom = new DOMDocument;
$dom->loadXML('blah');
$s = simplexml_import_dom($dom);

المثال 1: قراءة قائمة الأطعمة

 

1
2
3
4
5
6
7
8
$sx     = simplexml_load_file('iraqiFood.xml');
 
foreach ($sx->food as $item)
{
echo '
'.$item->name.'
';
}

 

كما نلاحظ في المثال يمكن الوصول الوصول إلى العناصر باستخدام “التحميل الزائد” والتعامل مع “عناصر المصفوفة” كما لو كانت جزءاً من الشيء sx.

يمكن أيضاً قراءة العناصر باستخدام الطريقة children في sx كما يلي:

foreach ($sx->children() as $item) { echo ”.$item->name.’ 

‘; }

المثال 2: قراءة عناصر معيّنة فقط

echo $sx->food[1]->name; //الخرج سيكون: الدليميه

سيتم تخزين العناصر في مصفوفة في الشيء sx مما يمكننا من الوصول إليها كما في الطريقة السابقة أعلاه.

المثال 3: قراءة العنصر بالكامل

لنأخذ شيفرة XML التالية:

منقول من: <a href="http://php.net">PHP Site</a>

لنحاول الآن قراءة العنصر source كما يلي:

echo $sx->food[0]->source;

سوف لن يظهر أي شيء!! لكن لماذا؟

لأن هناك عناصر أخرى داخل العنصر source وهي p و a فلا يستطيع المسفر قراءة هذه العناصر لأنه لم تسند إليه. وللتغلب على هذه المشكلة يمكننا قراءة العناصر كما يلي:

echo $sx->food[0]->source->p;

لاحظ أنه لن يتم قراءة العنصر a لأنه داخل العنصر p. يمكننا بواسطة الطريقة asXML قراءة جميع العناصر التي يحتويها العنصر (طبعاً إذا كانت عناصر موثوق بها فقط، بمعنى شيفرة HTML أو أي عناصر أخرى قابلة للفهم):

echo $sx->food[0]->source->asXML();

المثال 4: قراءة صفات العناصر

قراءة الصفة type للعنصر food:

echo $sx->food[0]->attributes()->type;

يمكن أيضاً استخدام مصفوفة لهذا الغرض كما يلي:

 

1
2
3
4
5
foreach ($sx->food[0]->attributes() as $attr)
{
echo $attr.'
';
}

المثال 5: استخدام XPath

المثال التالي يقوم بقراءة العنصر title لملف rss:

 

foreach ($rss->xpath('//title') as $title)
{
echo "
<h2>" . $title . "</h2>
";
}

الخاتمة

بهذا أكون قد انتهيت من أهم مواضيع PHP ألا وهو موضوع “التعامل مع XML“.

بانتظار تعليقاتكم :-)

عدد التعليقات 6

  • يوسف :

    شكرا و بارك الله فيك على المقالة الشيقة
    بانتظار المزيد أخي
    ربي يوفقك و يجازيك خيرا

  • أبوبكر الطائف :

    الأخ الكريم أحمد السلام عليكم ورحمة الله

    مقال مفيد وسهل ،،، أشكرك جزيل الشكر قمت بتنفيذ المقال ولأول مره أستطيع حل معضلة xml و php بصوره سهله وبسيطه ،،، لك جزيل الشكر واتمنى لك دوام التوفيق،،،

  • أحمد المياحي :

    وعليكم السلام
    على الرحب والسعة عزيزي

  • hassan :

    أخي شكرا لك على هذا الشرح

    و إن أمكن أن تساعدني : لدي قارئ فلاشي يعمل بملف XML و أريد التحكم بهذا الملف عن طريق الـ PHP فكيف يمكنني ذلك ؟

    يعني أضيف items داخل playlist و كل item يحتوي على title . artiste . path

  • continue :

    بجد أشكرك … مواضيع فعلاً أعجبتني .

  • الريم :

    اهنئك اخي احمد على الطرح العملاق والاكثر من رائع :)

تعليقك على الموضوع

خلاصات التعليقات RSS   التعقيبات

جميع الحقوق محفوظة لـ مدونة أحمد المياحي © 2017