تابع xml_set_unparsed_entity_decl_handler() در PHP
در PHP مجموعهای از توابع low-level برای پردازش XML بر پایهٔ کتابخانهٔ Expat وجود دارد. یکی از این توابع xml_set_unparsed_entity_decl_handler() است که به شما امکان میدهد هرگاه اعلانهای unparsed entity در DTD یک سند XML شناسایی شدند، یک callback مخصوص اجرا کنید. این تابع برای مواقعی کاربردی است که نیاز دارید اطلاعات مربوط به منابع غیر‑XML (مانند تصویرها یا فایلهای باینری) اعلامشده در DTD را جمعآوری یا پردازش کنید.
مفهوم Unparsed Entity در DTD
Unparsed entityها در DTD برای اشاره به منابعی استفاده میشوند که محتوایشان XML نیست؛ بهعنوان مثال تصاویر یا فایلهای رسانهای. نمونهٔ اعلان در DTD:
<![CDATA[
]]>در این مثال، موجودیت logo یک unparsed entity است که سیستم آیدی آن مسیر فایل و NDATA نشانگر نوع notation (مثلاً png) است.
شرح تابع و پارامترهای callback
تابع xml_set_unparsed_entity_decl_handler دو ورودی میگیرد: مرجع به parser و یک callback. callback باید شش پارامتر بپذیرد. جزئیات پارامترها را در جدول زیر میبینید:
| پارامتر | نوع / مقدار | توضیح |
|---|---|---|
| parser | resource | منبع parser (از xml_parser_create) |
| entity_name | string | نام موجودیت اعلامشده (مثلاً “logo”) |
| base | string|null | Base URI در زمان اعلان (در صورت وجود) |
| systemId | string|null | System identifier — معمولاً مسیر یا URL فایل |
| publicId | string|null | Public identifier اگر مشخص شده باشد |
| notationName | string|null | نام notation مرتبط با این unparsed entity |
مثال عملی: جمعآوری اطلاعات unparsed entity
<?php
$xml = '
<!DOCTYPE doc [
]>
Sample content';
$parser = xml_parser_create();
$unparsed = [];
xml_set_unparsed_entity_decl_handler(
$parser,
function($parser, $entity_name, $base, $systemId, $publicId, $notation_name) use (&$unparsed) {
$unparsed[$entity_name] = [
'base' => $base,
'systemId' => $systemId,
'publicId' => $publicId,
'notation' => $notation_name
];
}
);
if (!xml_parse($parser, $xml, true)) {
printf("XML Error: %s at line %dn",
xml_error_string(xml_get_error_code($parser)),
xml_get_current_line_number($parser)
);
}
xml_parser_free($parser);
print_r($unparsed);
?>در این مثال یک DTD داخلی داریم که دو unparsed entity اعلام کرده: logo و banner. callback در زمان پردازش DTD فراخوانی شده و اطلاعات مرتبط را در آرایهٔ $unparsed ذخیره میکند. پس از پایان parse، میتوانید این اطلاعات را برای فهرستبندی منابع، دانلود یا اعتبارسنجی استفاده کنید.
مثال بهینهتر با مدیریت خطا و مسیر نسبی
$resolved,
'publicId' => $publicId,
'notation' => $notation_name
];
});
if (!xml_parse($parser, $xml, true)) {
// لاگکردن خطا یا پرش از ادامهٔ پردازش
error_log("XML Parse error: " . xml_error_string(xml_get_error_code($parser)));
}
xml_parser_free($parser);
?>در نسخهٔ بهینه بالا، تلاش شده مسیرهای نسبی نسبت به base URI حل شوند و خطاها لاگ شوند. همیشه پیشنهاد میشود پس از xml_parse، parser را با xml_parser_free آزاد کنید تا نشتی منابع رخ ندهد.
موارد استفاده و نکات عملی
- ایندکس کردن منابع غیر‑XML موجود در DTD برای عملیات بعدی (مثلاً کپی فایلها، نمایش تصاویر).
- بررسی امنیتی: شناسایی منابع خارجی مخرب یا نامعتبر قبل از دانلود آنها.
- تطبیق با قواعد سیستم شما؛ مثلاً تبدیل اعلانهای موجودیت به رکورد در دیتابیس.
ملاحظات امنیتی و محدودیتها
- در صورتی که DTD به منابع خارجی اشاره کند، مراقب حملات XXE باشید. همیشه ورودیهای XML ناشناخته را با احتیاط پردازش کنید.
- xml_set_unparsed_entity_decl_handler بخشی از توابع قدیمی Expat در PHP است؛ برای پروژههای مدرن ممکن است استفاده از DOMDocument و libxml مناسبتر باشد مگر اینکه نیاز خاصی به پردازش stream‑based یا low-level داشته باشید.
- این handler فقط برای اعلانهای unparsed entity در DTD فراخوانی میشود؛ entityهای معمولی (parsed entities) اینجا گزارش نمیشوند.
مقایسهٔ سریع: Expat (xml_*) در برابر DOM
| ویژگی | xml_* (Expat) | DOM (libxml) |
|---|---|---|
| کنترل رویداد محور | خیر/بله (callbacks پایینسطح) | خیر (درختی) |
| دسترسی به اعلانهای DTD | بله (handlers مانند xml_set_unparsed_entity_decl_handler) | محدودتر/پیچیدهتر |
| کار با فایلهای بزرگ | بهتر (stream-friendly) | ممکن است حافظهبر |
جمعبندی
xml_set_unparsed_entity_decl_handler() یک ابزار مفید در هنگامی است که نیاز دارید اعلانهای unparsed entity در DTD را کشف و مدیریت کنید. این تابع اطلاعاتی مانند systemId، publicId و notation را در اختیار callback قرار میدهد و میتواند برای ایندکسینگ، دانلود یا بررسی امنیتی منابع غیر‑XML کاربردی باشد. با این حال، به دلیل مسائل امنیتی و قدمت API، قبل از استفاده در پروژههای جدید، گزینههای مدرنتر مثل DOMDocument یا بررسی دقیق رویههای بازخوانی DTD را در نظر بگیرید.
آیا این مطلب برای شما مفید بود ؟



