PHP و XML: انواع تجزیه گر ها و SimpleXML

15 مرداد 1398
درسنامه درس 26 از سری آموزش PHP 7
PHP و XML: انواع تجزیه گر ها و SimpleXML

XML در PHP

XML روشی جهت ساختاردهی به داده ها برای به اشتراک گذاری بین وب سایت ها است. چندین تکنولوژی دنیای وب مانند RSS و Podcast به صورت XML نوشته شده اند. خود XML نیز شباهت زیادی به HTML دارد با این تفاوت که شما تگ های خودتان را می سازید.

برای خواندن، به روز رسانی، ساختن و ویرایش XML به XML parser (تجزیه گر XML) نیاز دارید. زبان PHP دو نوع XML parser را در اختیار شما قرار می دهد:

  • Tree-Based Parsers (تجزیه گرهای درختی)
  • Event-Based Parsers (تجزیه گرهای رویداد-محور)

Event-Based Parsers و Tree-Based Parsers

تجزیه گر های درختی (Tree-based) تمام سند را در مموری نگه می دارند و ساختار XML را تبدیل به یک ساختار درختی می کنند. سپس تمام سند را بررسی کرده و به شما اجازه ی دسترسی به عناصر مختلف را می دهد (DOM). این نوع تجزیه گرها انتخاب بهتری برای XML های کوچک هستند اما اگر XML شما بزرگ باشد باعث بروز مشکلات متعددی خواهند شد.

نمونه هایی از تجزیه گرهای درختی:

  • SimpleXML
  • DOM

از طرفی تجزیه گرهای رویداد-محور (Event-based) تمام سند را در مموری نگه نمی دارند بلکه node ها را دانه دانه می خوانند و به شما اجازه می دهند که در لحظه با آن ها تعامل داشته باشید بنابراین زمانی که به node بعدی برسید node قبلی دور انداخته می شود. این نوع تجزیه گرها مناسب XML های بزرگ هستند؛ سریع تر تجزیه می کنند و مموری کمتری نیز مصرف می کنند.

نمونه هایی از تجزیه گر های رویداد-محور:

  • XMLReader
  • XML Expat Parser

آشنایی با SimpleXML

SimpleXML یک تجزیه گر درختی است و ما را قادر می سازد که به سادگی به نام عنصر، attribute ها، محتوای متنی و ... دسترسی داشته باشیم. در واقع SimpleXML سند XML شما را به یک ساختار داده تبدیل می کند که شما می توانید مانند اشیاء یا آرایه ها در آن گردش کنید. در مقایسه با DOM یا تجزیه گر Expat، تجزیه گر SimpleXML نیاز به تعداد خطوط کد کمتری برای خواندن محتوای متنی دارد.

در زبان PHP برای خواندن داده های XML از یک رشته از تابع ()simplexml_load_string استفاده می شود. فرض کنید متغیری داشته باشیم که داده های XML زیر را دارد:

$myXMLData = 
"<?xml version='1.0' encoding='UTF-8'?>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>";

مثال زیر به شما نشان می دهد که چطور از تابع ()simplexml_load_string برای خواندن رشته های XML استفاده کنید:

<!DOCTYPE html>
<html>
<body>

<?php
$myXMLData =
"<?xml version='1.0' encoding='UTF-8'?>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>";

$xml=simplexml_load_string($myXMLData) or die("Error: Cannot create object");
print_r($xml);
?>

</body>
</html>

مشاهده ی خروجی

همانطور که مشاهده می کنید خروجی این کد عبارت زیر خواهد بود:

SimpleXMLElement Object ( [to] => Tove [from] => Jani [heading] => Reminder [body] => Don't forget me this weekend! )

برای مدیریت خطا ها بهتر است از قابلیت های libxml استفاده کرده و در هنگام بارگذاری سند تمام خطاهای XML را دریافت کنید. سپس مانند آرایه ها در خطاها گردش کنید. مثال زیر همین کار را انجام می دهد:

<!DOCTYPE html>
<html>
<body>

<?php
libxml_use_internal_errors(true);
$myXMLData =
"<?xml version='1.0' encoding='UTF-8'?> 
<document> 
  <user>John Doe</wronguser> 
  <email>john@example.com</wrongemail> 
</document>"; 

$xml = simplexml_load_string($myXMLData);
if ($xml === false) {
    echo "Failed loading XML: ";
    foreach(libxml_get_errors() as $error) {
        echo "<br>", $error->message;
    }
} else {
    print_r($xml);
}
?>

</body>
</html>

مشاهده ی خروجی

خروجی کد بالا پیام زیر خواهد بود:

Failed loading XML:
Opening and ending tag mismatch: user line 3 and wronguser
Opening and ending tag mismatch: email line 4 and wrongemail

اما اگر بخواهید اطلاعات XML را از یک فایل بخوانید باید از تابع ()simplexml_load_file استفاده کنید. فرض کنید فایل XML ای به نام note.xml داشته باشیم که حاوی اطلاعات زیر است:

<?xml version="1.0" encoding="UTF-8"?>
<note>
  <to>Tove</to>
  <from>Jani</from>
  <heading>Reminder</heading>
  <body>Don't forget me this weekend!</body>
</note>

برای خواندن اطلاعات این فایل از تابع ()simplexml_load_file به روش زیر استفاده می کنیم:

<!DOCTYPE html>
<html>
<body>

<?php
$xml=simplexml_load_file("note.xml") or die("Error: Cannot create object");
print_r($xml);
?>

</body>
</html>

مشاهده ی خروجی

خروجی این مثال عبارت زیر می باشد:

SimpleXMLElement Object ( [to] => Tove [from] => Jani [heading] => Reminder [body] => Don't forget me this weekend! )

دریافت مقدار node ها

تا این قسمت توانستیم رشته ها را بخوانیم اما اگر قصد خواندن مقادیر node ها را داشته باشیم چطور؟ برای این کار روش زیر را انجام می دهیم:

<!DOCTYPE html>
<html>
<body>

<?php
$xml=simplexml_load_file("note.xml") or die("Error: Cannot create object");
echo $xml->to . "<br>";
echo $xml->from . "<br>";
echo $xml->heading . "<br>";
echo $xml->body;
?> 

</body>
</html>

مشاهده ی خروجی

خروجی کد بالا عبارت زیر خواهد بود:

Tove
Jani
Reminder
Don't forget me this weekend!

حالا فرض کنید فایلی به نام books.xml داشته باشیم که شامل محتویات زیر باشد:

<?xml version="1.0" encoding="utf-8"?>
<bookstore>
  <book category="COOKING">
    <title lang="en">Everyday Italian</title>
    <author>Giada De Laurentiis</author>
    <year>2005</year>
    <price>30.00</price>
  </book>
  <book category="CHILDREN">
    <title lang="en">Harry Potter</title>
    <author>J K. Rowling</author>
    <year>2005</year>
    <price>29.99</price>
  </book>
  <book category="WEB">
    <title lang="en-us">XQuery Kick Start</title>
    <author>James McGovern</author>
    <year>2003</year>
    <price>49.99</price>
  </book>
  <book category="WEB">
    <title lang="en-us">Learning XML</title>
    <author>Erik T. Ray</author>
    <year>2003</year>
    <price>39.95</price>
  </book>
</bookstore>

اگر بخواهیم مقدار عنصر <title> در <book> اول و دوم را بگیریم می گوییم:

<!DOCTYPE html>
<html>
<body>

<?php
$xml=simplexml_load_file("books.xml") or die("Error: Cannot create object");
echo $xml->book[0]->title . "<br>";
echo $xml->book[1]->title;
?> 

</body>
</html>

مشاهده ی خروجی

خروجی این کد عبارت زیر خواهد بود:

Everyday Italian
Harry Potter

به سراغ یک مثال دیگر برویم. فرض کنید می خواهیم در فایل books.xml گردش کرده و مقادیر <title> و <author> و <year> و <price> را دریافت کنیم. در این صورت می توانیم کد ها را به شکل زیر بنویسیم:

<!DOCTYPE html>
<html>
<body>

<?php
$xml=simplexml_load_file("books.xml") or die("Error: Cannot create object");
foreach($xml->children() as $books) { 
        echo $books->title . ", "; 
        echo $books->author . ", "; 
        echo $books->year . ", ";
        echo $books->price . "<br>"; 
} 
?> 

</body>
</html>

مشاهده ی خروجی

خروجی کد بالا عبارت زیر خواهد بود:

Everyday Italian, Giada De Laurentiis, 2005, 30.00
Harry Potter, J K. Rowling, 2005, 29.99
XQuery Kick Start, James McGovern, 2003, 49.99
Learning XML, Erik T. Ray, 2003, 39.95

دریافت مقدار attribute ها

حالا اگر بخواهیم مقدار attribute ها را دریافت کنیم چطور؟ در مثال زیر می خواهیم مقدار attribute ای به نام category را از عنصر اولِ <book> بگیریم. سپس می خواهیم مقدار attribute دیگری به نام lang را از <title> در عنصر دومِ <book> نیز بگیریم:

<!DOCTYPE html>
<html>
<body>

<?php
$xml=simplexml_load_file("books.xml") or die("Error: Cannot create object");
echo $xml->book[0]['category'] . "<br>";
echo $xml->book[1]->title['lang']; 
?> 

</body>
</html>

مشاهده ی خروجی

خروجی این کد:

COOKING
en

مثال زیر مقادیر attribute های <title> را می گیرد:

<!DOCTYPE html>
<html>
<body>

<?php
$xml=simplexml_load_file("books.xml") or die("Error: Cannot create object");
foreach($xml->children() as $books) { 
    echo $books->title['lang'];
    echo "<br>"; 
} 
?> 

</body>
</html>

مشاهده ی خروجی

خروجی این کد نیز عبارات زیر خواهند بود:

en
en
en-us
en-us

امیدوارم این مقاله برایتان لذت بخش بوده باشد.

تمام فصل‌های سری ترتیبی که روکسو برای مطالعه‌ی دروس سری آموزش PHP 7 توصیه می‌کند:
نویسنده شوید

دیدگاه‌های شما

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.