С самого начала у вас должно быть понимание, что Query можно вызывать только для DomXPath, который инициализируется только с DomDocument. Всё. Ему нельзя подсовывать DomNodeList или DomNode. Только DomDocument. Из-за этого нужно применять другой подход к получению данных.
Вы думаете, что можно найти запросом таблицу, потом ещё одним запросом найти в ней DIV, потом ещё одним запросом найти в этом DIV какой-нибудь SPAN, а в нём ещё одним запросом найти A. С DomXPath так нельзя работать. Хотите найти элемент, ищите его сразу — от корня DOM.
Прямо сейчас могу что-то неточно написать в самих XPath-запросах, но делать нужно примерно так:
$pageDom = new DOMDocument();
@$pageDom->loadHTML($pageHtml);
$pageXPath = new DomXPath($pageDom);
$elementsName = $pageXPath->query('.//table/.//div[class="name"]');
$elementsDescription = $pageXPath->query('.//table/.//div[class="description"]');
$elementsRating = $pageXPath->query('.//table/.//div[class="rating"]');
$elements = array();
for ($i = 0; $i < $elementsName->length; $i++) {
$elements[] = array(
'name' => $elementsName->item($i)->nodeValue,
'description' => $elementsDescription->item($i)->nodeValue,
'rating' => $elementsRating->item($i)->nodeValue,
);
}
//Profit
Однако!
Якориться к предыдущим результатам поиска всё-таки возможно. У функции DomXPath::query есть необязательный параметр с типом DOMNode. Получаются такие неявные под-запросы.
$pageDom = new DOMDocument();
@$pageDom->loadHTML($pageHtml);
$pageXPath = new DomXPath($pageDom);
$elementsDom = $pageXPath->query('.//table/tr');
$elements = array();
foreach ($elementsDom as $elementDom) {
$elements[] = array(
'name' => $pageXPath->query('.//div[class="name"]', $elementDom)->item(0)->nodeValue,
'description' => $pageXPath->query('.//div[class="description"]', $elementDom)->item(0)->nodeValue,
'rating' => $pageXPath->query('.//div[class="rating"]', $elementDom)->item(0)->nodeValue,
);
}
Особенность в том, что используется всё тот же $pageXPath, а не происходит попытка создать из DOMNode отдельный DOMXPath. И дальше происходит поиск в контексте предыдущих результатов запроса — за счёт добавления в функцию DomXPath::query дополнительного параметра, уточняющего контекст, в котором происходит поиск — DomXPath::query(строка_запроса, контекст_поиска). Так что в такой ситуации «.//div[class="name"]» будет искаться не во всём документе, а только в текущей строке TR.