【问题标题】:Use DOMDocument to remove nodes with short content length使用 DOMDocument 删除内容长度较短的节点
【发布时间】:2014-06-02 16:54:19
【问题描述】:

拥有:

$content= 
'<div id="parent">
    <div class="children">
        This is short content
    </div>
    <div class="children">
        This is a very long content even longer than the Short content
    </div>
    <p>
        This is a Short content in a paragraph
    </p>
        This is a Short content without a html elemnt
</div>';

我可以通过class(或id)使用DOMDocument 删除节点,如下所示:

$dom->loadHTML($content);
$xpath = new DOMXpath($dom);
if($divToRemove = $xpath->query('.//div[@class="children"]')->item(0))
    $divToRemove->parentNode->removeChild($divToRemove);
$content = $dom->saveHTML();

使用上面的代码,我可以从$content 中删除第一个div。但是如何删除内部文本较短的孩子,例如少于 20 个字符?

编辑
我不知道子元素。它可以是 &lt;div&gt;&lt;p&gt; 或其他。
我想删除父母 &lt;div&gt;
的每个短长度的孩子 是否有任何Xpath 查询来选择节点的长度?

这是我想要的输出:

$content= 
'<div id="parent">
    <div class="children">
        This is a very long content even longer than the Short content
    </div>
</div>';

【问题讨论】:

    标签: php html-parsing domdocument removechild


    【解决方案1】:

    divp 元素节点不是带有字符串的节点。这始终是文本节点。但是,节点可以在 Xpath 中转换为字符串。这是需要的两个字符串函数。

    string-length()

    返回字符串的字符长度。如果提供了节点列表,则将列表的第一个节点转换为字符串。

    normalize-space()

    将字符串中的所有空白组转换为单个空格并将它们从开头和结尾剥离。

    但首先要了解一些上下文:

    $context = $xpath->evaluate('//div[@id = "parent"]')->item(0);
    

    现在为具有排序内容的节点构建一个表达式:

    各种节点、元素、文本节点、cmets、...

    node()

    ...在规范化空格后字符串长度小于或等于 50:

    node()[string-length(normalize-space(.)) &lt;= 50]

    放在一起:

    $dom = new DOMDocument();
    $dom->loadHtml($content);
    $xpath = new DOMXPath($dom);
    
    $context = $xpath->evaluate('//div[@id = "parent"]')->item(0);
    
    $maxLength = 50;
    $expression = 'node()[string-length(normalize-space(.)) <= '.$maxLength.']';
    foreach ($xpath->evaluate($expression, $context) as $node) {
      $node->parentNode->removeChild($node);
    }
    
    echo $dom->saveHtml($context);
    

    输出:

    <div id="parent"><div class="children">
            This is a very long content even longer than the Short content
        </div></div>
    

    上下文仅用于将原始 div 保存为 HTML。 DOMDocument::loadHtml() 将添加 htmlbody 元素。

    这个例子没有什么不同,但我建议对所有 Xpath 表达式使用DOMXpath::evaluate()DOMXpath::query() 不支持返回标量值的 Xpath 表达式。见:https://stackoverflow.com/a/23796070/2265374

    【讨论】:

      【解决方案2】:
      $dom->loadHTML($content);
      $xpath = new DOMXpath($dom);
      
      if($divToRemove = $xpath->query('.//div[@class="children"]')->item(0)) {
          if(20 > strlen($xpath->query('.//div[@class="children"]')->item(0))) {
              $divToRemove->parentNode->removeChild($divToRemove);
          }
      }
      
      $content = $dom->saveHTML();
      

      【讨论】:

      • 我认为有比在项目上使用 srtlen 更短的功能。我也不知道父节点的子节点。我不知道它是

        还是

      • 请注意编辑
      猜你喜欢
      相关资源
      最近更新 更多
      热门标签