متد xpath() در PHP
متد xpath() یکی از ابزارهای قدرتمند برای جستجو و واکشی گرهها در اسناد XML (و تا حدودی HTML ساختیافته) است. در PHP دو رویکرد رایج برای کار با XPath وجود دارد: متد xpath() در SimpleXML و کلاس DOMXPath که همراه با DOMDocument استفاده میشود. در این مقاله به هر دو روش، نکات مربوط به namespaceها، مثالهای عملی، بهینهسازی و خطایابی میپردازیم.
چرا XPath مهم است؟
- عبارات XPath امکان انتخاب دقیق گرهها، صفتها و مقادیر متنی را فراهم میکنند.
- با استفاده از توابعی مثل contains(), starts-with(), count() میتوان معیارهای پیچیدهتری اعمال کرد.
- برای پردازش فیدهای XML، پاسخهای APIها و اسناد HTML ساختاریافته بسیار کارآمد است.
1. استفاده از SimpleXML::xpath()
اگر سند XML ساده دارید و میخواهید سریع مقادیر را واکشی کنید، SimpleXML مناسب و متد xpath() بسیار ساده است.
$xml = simplexml_load_string('
Ali
Sara
');
$results = $xml->xpath('/books/book[author="Ali"]/title');
foreach ($results as $title) {
echo (string)$title . PHP_EOL;
}
در این مثال، متد xpath() آرایهای از گرههای SimpleXMLElement برمیگرداند که با عبارت XPath انتخاب شدهاند. برای تبدیل مقدار گره به رشته باید (string) اعمال شود.
نکات مهم در SimpleXML
- نتیجه همیشه آرایه است؛ حتی اگر یک گره پیدا شود.
- برای اسناد با namespace باید از registerXPathNamespace در SimpleXML استفاده کرد.
- برای اسناد بزرگ یا نیاز به عملیات پیچیدهتر، DOMXPath گزینه بهتری است.
2. استفاده از DOMDocument و DOMXPath (پیشنهاد شده برای پروژههای بزرگ)
DOMXPath انعطافپذیری بیشتری دارد، مخصوصاً هنگام کار با namespaceها، HTML نامنظم یا اصلاح درخت DOM.
$doc = new DOMDocument();
libxml_use_internal_errors(true);
$doc->loadXML($xmlString);
libxml_clear_errors();
$xpath = new DOMXPath($doc);
$nodes = $xpath->query('/books/book[@id="b1"]/title');
foreach ($nodes as $node) {
echo $node->nodeValue . PHP_EOL;
}
اینجا از DOMDocument برای بارگذاری XML استفاده شده و سپس شی DOMXPath برای اجرای query فراخوانی میشود. تابع query یک DOMNodeList برمیگرداند که میتوان روی آن پیمایش کرد.
ثبت namespace در DOMXPath
$doc = new DOMDocument();
$doc->loadXML($xmlWithNS);
$xpath = new DOMXPath($doc);
$xpath->registerNamespace('ns', 'http://example.com/ns');
$nodes = $xpath->query('//ns:element');
اگر XML شما از namespace استفاده کرده، قبل از اجرای عبارتهایی که شامل پیشنام (prefix) هستند باید namespace را ثبت کنید. بدون ثبت، انتخاب مبتنی بر namespace کار نخواهد کرد.
3. مثالهای کاربردی XPath
- انتخاب بر اساس متن: //book[title=”PHP Essentials”]
- فیلتر بر اساس contains: //book[contains(title, ‘PHP’)]
- انتخاب صفت: //book[@id=’b2′]
- انتخاب مقدار عددی: count(//book) (DOMXPath->evaluate)
$count = $xpath->evaluate('count(//book)');
echo "Number of books: " . (int)$count . PHP_EOL;
تابع evaluate در DOMXPath میتواند مقادیر عددی یا رشتهای برگرداند و برای توابع XPath مفید است. نکته: query همیشه NodeList برمیگرداند در حالی که evaluate بسته به عبارت میتواند مقدار دیگر بازگرداند.
4. مشکلات رایج و خطایابی
- خطای namespace: فراموش کردن registerNamespace → نتیجه خالی.
- HTML نامنظم: برای HTML بهتر است از loadHTML و سپس DOMXPath استفاده کنید و از libxml_use_internal_errors برای جلوگیری از هشدارها استفاده کنید.
- نتایج خالی: مطمئن شوید مسیر XPath دقیق و حساس به حروف است و از // بیمورد دوری کنید (ممکن است کند باشد).
5. مقایسه مختصر SimpleXML::xpath() و DOMXPath
| ویژگی | SimpleXML::xpath() | DOMXPath |
|---|---|---|
| سهولت استفاده | بسیار ساده | متوسط |
| پشتیبانی از namespace | با registerXPathNamespace | قویتر و انعطافپذیر |
| عملیات پیچیده | محدود | قابل توسعه |
| بهینه برای اسناد بزرگ | کمتر مناسب | بسیار مناسب |
6. بهینهسازی و نکات عملکردی
- از استفادهٔ مفرط از // در بالا به پایین پرهیز کنید؛ مسیرهای دقیقتر سریعتر هستند.
- عبارات پیچیده را از طریق registerNamespace و توابع محلی ساده کنید.
- برای پردازش دستهای، یک بار DOMDocument بسازید و چندین query روی همان شیء اجرا کنید تا از بارگذاری مکرر جلوگیری شود.
- برای HTML نامنظم ابتدا آن را با Tidy پاک کنید یا از loadHTML با تنظیمات مناسب استفاده کنید.
7. مثال پیشرفته: یافتن لینکها با متن مشخص در HTML
$html = 'HomeProfile';
$doc = new DOMDocument();
libxml_use_internal_errors(true);
$doc->loadHTML($html);
libxml_clear_errors();
$xpath = new DOMXPath($doc);
$nodes = $xpath->query('//a[contains(normalize-space(.), "Profile")]');
foreach ($nodes as $a) {
echo $a->getAttribute('href') . PHP_EOL;
}
در این نمونه از normalize-space و contains برای پیدا کردن لینکهایی که متنشان شامل “Profile” است استفاده شده است. loadHTML برای HTML نامنظم مناسبتر از loadXML است.
خلاصه و جمعبندی
متد xpath() در SimpleXML برای کارهای سریع و ساده مناسب است؛ اما برای پروژههای پیچیده، اسناد بزرگ یا نیاز به کنترل کاملتر DOM، کلاس DOMXPath همراه با DOMDocument انتخاب بهتری است. نکات مهم شامل مدیریت namespace، استفاده از evaluate برای مقادیر غیر NodeList و بهینهسازی مسیرها است. با ترکیب درست این ابزارها میتوانید پردازش قوی و منعطفی روی XML و HTML در PHP پیاده کنید.
آیا این مطلب برای شما مفید بود ؟



