【问题标题】:How to remove elements from the DOM if they are consecutive如果元素是连续的,如何从 DOM 中删除元素
【发布时间】:2019-11-20 04:30:24
【问题描述】:

我继承了以下 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 类并将其删除即可。

或者有没有更简洁的方法来实现这一点?

【问题讨论】:

  • 这里的规则不清楚。 Record F 和 G 为什么特别?
  • @mplungjan 我们只想显示前 5 个元素(记录)。否则页面会太长。

标签: php html dom xpath


【解决方案1】:

您可以在当前的 foreach 之后添加一个额外的...

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

这里的 XPath 正在寻找一个 &lt;div class="year"&gt; 元素,然后只查看下一个 &lt;div&gt; 标记以获得相同的东西(following-sibling::div[1] 将它限制为仅在当前标记之后的下一个 div 标记)。

【讨论】:

    【解决方案2】:

    这是一个简单的 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>

    【讨论】:

      【解决方案3】:

      我最终使用了以下代码:

      $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);
      

      它允许我在不使用嵌套循环的情况下一次性实现目标

      【讨论】:

        猜你喜欢
        • 2012-09-29
        • 2015-01-29
        • 2014-09-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-24
        • 1970-01-01
        • 2021-01-16
        • 1970-01-01
        相关资源
        最近更新 更多