DOMDocument::getElementsByTagName : только X первых элементов

У меня есть следующий код:

<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_URL, $url);
$doc = new DomDocument;
$doc->preserveWhiteSpace = false;

if ($doc->loadHtml(curl_exec($ch)))
    $anchors = $doc->getElementById('comments')->getElementsByTagName('a');
?>

который ищет на удаленной странице все ссылки (‹ тег >) в div комментариев.

Я хотел бы, чтобы эта функция возвращала только 50 первых тегов ‹ a > без разбора всего div. Это возможно ? И если да, то как?

Заранее спасибо.


person roberto06    schedule 05.05.2014    source источник
comment
Поскольку вы используете DOMDocument, весь div уже проанализирован. Даже весь документ. ... php.net/LimitIterator   -  person hakre    schedule 08.05.2014


Ответы (1)


Используйте выражение XPath:

$elements = 50;

$doc = new DOMDocument;
$doc->loadHTML($html);

$xpath = new DOMXPath($doc);
$anchors = $xpath->query(
    sprintf('//div[@id="comments"]/a[position() <= %d]', $elements)
);

Демо

person Amal Murali    schedule 05.05.2014
comment
Как это будет работать? Есть только один div с комментариями ID, который может содержать более 10000 ссылок. РЕДАКТИРОВАТЬ: ответил до того, как вы отредактировали бит XPath. Я попробую это. - person roberto06; 05.05.2014
comment
Я бы посоветовал сначала проверить длину элемента тегов <a>, если она превышает 50, затем выполнить цикл до этого, иначе обрезать до его длины. - person Shankar Narayana Damodaran; 05.05.2014
comment
@ roberto06 roberto06 вы, конечно, также можете использовать «встречное решение», но тогда foreach поверх ответа getElementsByTagName('a'). - person giorgio; 05.05.2014
comment
@AmalMurali Это (вроде) работает. Теперь я сталкиваюсь с другими проблемами: 1. Контейнер не всегда является ‹ div ›, он также может быть ‹ul › или ‹ ol ›, среди прочего. Мне нужно проверить контейнер с комментариями к идентификатору, независимо от имени его тега. 2. Ссылки редко находятся непосредственно в контейнере, часто есть еще один подраздел или ‹ p › или что-то еще. Как я могу получить 50 первых ссылок в контейнере, независимо от их глубины? - person roberto06; 05.05.2014
comment
@roberto06: Тогда измени свое выражение на '//*[@id="comments"]/a[position() <= %d]'. - person Amal Murali; 05.05.2014
comment
@AmalMurali Спасибо, это решило проблему с контейнером. Однако у меня все еще есть проблема при попытке получить ссылки независимо от их глубины. См. здесь: демонстрация - person roberto06; 05.05.2014
comment
@ roberto06: Это сильно отличается от вашей реальной проблемы. Пожалуйста, опубликуйте его как новый вопрос. - person Amal Murali; 05.05.2014
comment
Сделаю. Спасибо за помощь. - person roberto06; 05.05.2014
comment
Не могу проголосовать, у меня нет необходимой репутации. Какой позор, вы очень помогли. Во всяком случае, мне удалось решить эту последнюю проблему, похоже, мне просто нужно было добавить скобки к '//*[@id="comments"]//a', и это работает как шарм, см. здесь: Демо - person roberto06; 05.05.2014