ویژگی تصویر

تابع xml_set_object() در PHP — معرفی و کاربردها

  /  PHP   /  تابع xml_set_object() در PHP
بنر تبلیغاتی الف
آموزش PHP

تابع xml_set_object() یکی از توابع کتابخانهٔ XML مبتنی بر Expat در PHP است که برای اتصال یک شیء (object) به یک پارسر XML استفاده می‌شود. زمانی که این شیء تنظیم شود، نام متدهایی که به عنوان هندلرها (handlers) مشخص شده‌اند به‌صورت متدهای آن شیء فراخوانی می‌شوند. این روش کمک می‌کند تا ساختار کد منظم‌تر شده و منطق پردازش XML در کلاسی مستقل محصور گردد.

موقعیت کاربرد

  • هنگام استفاده از پارسر رویدادمحور (SAX-like) در PHP مانند توابع xml_parser_create و xml_set_element_handler.
  • وقتی می‌خواهید متدهای handler به‌صورت عضو یک کلاس اجرا شوند (برای نگهداری وضعیت، متغیرهای داخلی و روش‌های کمکی).
  • برای نظم‌بخشی کد و حذف نیاز به استفاده از توابع سراسری یا بسته‌بندی اطلاعات در متغیرهای global.

نحو، پارامترها و مقدار بازگشتی

امضاتوضیح
bool xml_set_object(resource $parser, object $object)پارسر XML و شیء مورد نظر را می‌پذیرد و در صورت موفقیت true برمی‌گرداند.

پارامترها

  • $parser: منبع (resource) پارسر که با xml_parser_create() ساخته شده است.
  • $object: شیئی از کلاس مورد نظر که متدهای handler در آن تعریف شده‌اند.

هندلرهای معمول همراه با xml_set_object

  • xml_set_element_handler — start و end عناصر
  • xml_set_character_data_handler — داده‌های متنی بین تگ‌ها
  • xml_set_default_handler — هندلر پیش‌فرض
  • xml_set_processing_instruction_handler و دیگر هندلرهای رویدادمحور

مثال عملی ساده

depth++;
        echo str_repeat("  ", $this->depth - 1) . "Start: $namen";
        if (!empty($attrs)) {
            foreach ($attrs as $k => $v) {
                echo str_repeat("  ", $this->depth) . "Attr: $k => $vn";
            }
        }
    }

    function endElement($parser, $name) {
        echo str_repeat("  ", $this->depth - 1) . "End: $namen";
        $this->depth--;
    }

    function characterData($parser, $data) {
        $trim = trim($data);
        if ($trim !== '') {
            echo str_repeat("  ", $this->depth) . "Data: $trimn";
        }
    }
}

$xml = "HelloWorld";

$parser = xml_parser_create();
$handler = new MyXmlParser();

// اتصال شیء به پارسر
xml_set_object($parser, $handler);

// تعیین هندلرها به صورت نام متد (پرونده نام‌ها مختصر و خواناست)
xml_set_element_handler($parser, "startElement", "endElement");
xml_set_character_data_handler($parser, "characterData");

if (!xml_parse($parser, $xml, true)) {
    $err = xml_error_string(xml_get_error_code($parser));
    $line = xml_get_current_line_number($parser);
    echo "XML Error: $err at line $linen";
}

xml_parser_free($parser);
?>

در این مثال، یک کلاس MyXmlParser تعریف شده که سه متد برای شروع عنصر، پایان عنصر و داده‌های متنی دارد. پس از ساخت پارسر، با xml_set_object() شیء را به پارسر متصل می‌کنیم و سپس نام متدها را در xml_set_element_handler و xml_set_character_data_handler می‌دهیم. هنگام تجزیهٔ XML، پارسر این نام‌ها را به متدهای شیء مپ می‌کند و آنها را فراخوانی می‌کند.

نکات فنی و بهترین شیوه‌ها

  • نام متدها به صورت رشته داده می‌شوند — parser آنها را به عنوان متدهای شیء فراخوانی می‌کند، بنابراین مطمئن شوید که نام‌ها دقیقاً با متدهای کلاستان مطابقت دارند.
  • اگر xml_set_object() صدا زده نشود، پارسر انتظار دارد که هندلرها توابع سراسری یا قابل فراخوانی باشند (callable).
  • برای نگهداری وضعیت بین فراخوانی‌ها (مثل عمق درخت، شمارنده و …)، کلاس مناسب‌تر و ایمن‌تر از متغیرهای سراسری است.
  • همیشه خطاها را با xml_get_error_code و xml_error_string بررسی کنید و در صورت نیاز اطلاعات خط (line) را با xml_get_current_line_number بدست آورید.

بازده، امنیت و سازگاری

توابع پارسر Expat سریع و سبک هستند ولی نسبت به روش‌های DOM و SimpleXML سطح پایین‌تر و رویدادمحورند. اگر نیاز به تغییر کامل درخت XML یا انتخاب XPath دارید، بهتر است از DOMDocument یا SimpleXML استفاده کنید. با این حال، برای XML‌های بزرگ که نمی‌خواهید کل درخت را در حافظه بار کنید، پارسر رویدادمحور با xml_set_object مناسب و حافظه‌پسند است.

مثال پیشرفته — تبدیل خطا به Exception و نگهداری وضعیت

buffer .= $data;
    }

    public function parse($xml) {
        $parser = xml_parser_create();
        xml_set_object($parser, $this);
        xml_set_element_handler($parser, "startElement", "endElement");
        xml_set_character_data_handler($parser, "characterData");

        try {
            if (!xml_parse($parser, $xml, true)) {
                $code = xml_get_error_code($parser);
                $err = xml_error_string($code);
                $line = xml_get_current_line_number($parser);
                throw new XmlException("XML parse error: $err at line $line");
            }
        } catch (XmlException $e) {
            xml_parser_free($parser);
            throw $e;
        }

        xml_parser_free($parser);
    }
}
?>

در این قطعه، کلاس SafeParser وضعیت را در فیلدهای داخلی ذخیره می‌کند و یک لایهٔ مدیریت خطا اضافه شده تا خطاهای منطقی یا پارسینگ را به Exception تبدیل کند. توجه کنید که در صورت بروز Exception باید پارسر را آزاد کنیم تا نشت منبع رخ ندهد.

روش‌های جایگزین و توصیه‌های عملی

  • برای پردازش‌های ساده و دسترسی آسان به عناصر، از SimpleXML استفاده کنید (خواناتر و مدرن‌تر برای بیشتر نیازها).
  • برای XML‌های حجیم یا جریان (streaming)، پارسر رویدادمحور همراه با xml_set_object مناسب‌تر است چرا که حافظه کمتری مصرف می‌کند.
  • در پروژه‌های جدید PHP، بررسی کنید که ext-xml روی سرور فعال باشد؛ در برخی کانتینرها یا محیط‌های مینیمال ممکن است غیر فعال باشد.

جمع‌بندی

تابع xml_set_object() سازوکار ساده‌ای برای متصل‌کردن یک شیء به پارسر XML فراهم می‌کند تا رویدادهای پارسینگ به متدهای آن شیء ارسال شوند. این روش باعث خوانایی، قابلیت نگهداری و نگهداری وضعیت بین هندلرها می‌شود. اما در انتخاب بین روش‌های موجود (SimpleXML، DOM، XMLReader و پارسر Expat) باید بر پایهٔ نیازهای حافظه، اندازهٔ XML و نوع پردازش تصمیم‌گیری کنید.

آیا این مطلب برای شما مفید بود ؟

خیر
بله
موضوعات شما در انجمن: