DOMXpath->query() и относительные пути в запросах

понедельник, 30 января 2012 г.

DOMXpath очень удобно использовать для парсинга страниц. Это раньше все регулярками делалось, жутко неудобно. А xpath значительно упрощает эту процедуру. Конечно же, удобней когда работаешь с валидным html или xml документом. Простую html страницу к полной валидности вам поможет привести такой инструмент как tidy. Список его опций довольно богат, да и информацию о нем найти можно. Или я как-нибудь напишу. Но сейчас не об этом.

У DOMXpath есть метод query(), который и делает выборку по нашему запросу. Сам запрос передается первым параметром. Но иногда возникает необходимость сделать еще один запрос внутрь предыдущего результата. Как раз вторым параметром в метод query() идет $contextnode.


И если кто знает и помнит, то в xpath с // начинаются, так называемые, абсолютные пути. Я просто приведу пример из одного комментария со страницы описания метода и вы сразу все поймете:


<?php
    $xml = "<?xml version='1.0' encoding='UTF-8'?>
        <test>
            <tag1>
                <uselesstag>
                    <tag2>test</tag2>
                </uselesstag>
            </tag1>
            <tag2>test2</tag2>
        </test>";
   
    $dom = new DomDocument();
    $dom->loadXML($xml);
    $xpath = new DomXPath($dom);
   
    $tag1 = $dom->getElementsByTagName("tag1")->item(0);
   
    echo $xpath->query("//tag2")->length; //выведет 2 -> верно
    
    echo $xpath->query("//tag2", $tag1)->length; 
    //выведет 2 -> неверно, запрос не "относительный"
    
    echo $xpath->query(".//tag2", $tag1)->length; 
    //выведет 1 -> верно (заметьте точку перед //)
?>

То есть, если хочешь выбрать все нужные тебе элементы при помощи абсолютного пути (запроса) внутри какого-то объекта DOMNode, то перед // необходимо ставить точку.
Это не баг и не "фича". Это не до конца описанный функционал, так скажем.

Copyright © 2010 WEB IT blog