Как удалить элементы из DOM, если они являются последовательными - PullRequest
0 голосов
/ 10 июля 2019

Я унаследовал следующий фрагмент кода PHP, который удаляет элементы из DOM, прежде чем помещать содержимое на страницу. Мы только хотим, чтобы первые 5 элементов не имели слишком длинную страницу

Предполагая, что код извлекает фрагмент HTML, структурированный следующим образом:

<div class='year'>2019</div>
<div class='record'>Record A</div>
<div class='record'>Record B</div>
<div class='year'>2018</div>
<div class='record'>Record C</div>
<div class='record'>Record D</div>
<div class='record'>Record E</div>
<div class='year'>2017</div>
<div class='record'>Record F</div>
<div class='year'>2016</div>
<div class='record'>Record G</div>

Теперь фрагмент кода ниже удаляет все лишние records:

$dom = new DOMDocument();
// be sure to load the encoding
$dom->loadHTML('<?xml encoding="utf-8" ?>' . $tmp);
// let's use XPath
$finder = new DomXPath($dom);
// set the limit
$limit = 5; $cnt = 0;
// and remove unwanted elements
foreach($finder->query("//*[contains(@class, 'record')]") as $elm ) {
    if ($cnt >= $limit)
        $elm->parentNode->removeChild($elm);
        $cnt++;
    }
// finally, echo
echo $dom->saveHTML($dom->documentElement);

Логически я получаю следующий HTML-код:

<div class='year'>2019</div>
<div class='record'>Record A</div>
<div class='record'>Record B</div>
<div class='year'>2018</div>
<div class='record'>Record C</div>
<div class='record'>Record D</div>
<div class='record'>Record E</div>
<div class='year'>2017</div>
<div class='year'>2016</div>

Как я мог бы идентифицировать все элементы, имеющие класс year и имеющий следующий родной брат, также имеющий этот класс, и удалить его? (вот что бы получить элемент 2017)

Тогда я полагаю, что будет только вопрос проверки, имеет ли последний элемент класс year, и удаление его.

Или есть более чистый способ добиться этого?

Ответы [ 3 ]

1 голос
/ 10 июля 2019

Вы можете добавить дополнительный foreach после текущего ...

foreach($finder->query("//div[@class='year']/following-sibling::div[1][@class='year']") 
        as $elm ) {
    $elm->parentNode->removeChild($elm);
}

Здесь XPath ищет элемент <div class="year">, а затем только ищет следующий тег <div> для той же вещи (following-sibling::div[1] ограничивает его следующим тегом div после текущего).

0 голосов
/ 15 июля 2019

В итоге я набрал следующий код:

$dom = new DOMDocument();
// be sure to load the encoding
$dom->loadHTML('<?xml encoding="utf-8" ?>' . $tmp);
// let's use XPath
$finder = new DomXPath($dom);
foreach($finder->query("(//*[contains(@class, 'record')])[5]/following-sibling::*") as $elm) {
    $elm->parentNode->removeChild($elm);
    }
// finally, echo
echo $dom->saveHTML($dom->documentElement);

это позволило мне достичь цели за 1 проход без использования вложенных циклов

0 голосов
/ 10 июля 2019

Вот простой метод JS на тот случай, если вы хотите сделать это на клиенте вместо

const recs = document.querySelectorAll(".record");
const divs = document.querySelectorAll("div");
const lastRec = recs[4];
let found = false;
divs.forEach(div => {
  div.classList.toggle("hide",found)
  if (div === lastRec) found = true
})
.hide { display:none}
<div class='year'>2019</div>
<div class='record'>Record A</div>
<div class='record'>Record B</div>
<div class='year'>2018</div>
<div class='record'>Record C</div>
<div class='record'>Record D</div>
<div class='record'>Record E</div>
<div class='year'>2017</div>
<div class='record'>Record F</div>
<div class='year'>2016</div>
<div class='record'>Record G</div>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...