从HTML中去除空格

36

我有如下 HTML 代码:

<div class="wrap">
    <div>
        <div id="hmenus">
            <div class="nav mainnavs">
                <ul>
                    <li><a id="nav-questions" href="/questions">Questions</a></li>
                    <li><a id="nav-tags" href="/tags">Tags</a></li>
                    <li><a id="nav-users" href="/users">Users</a></li>
                    <li><a id="nav-badges" href="/badges">Badges</a></li>
                    <li><a id="nav-unanswered" href="/unanswered">Unanswered</a></li>
                </ul>
            </div>
        </div>
    </div>
</div>

如何使用PHP删除标签之间的空格?

我们需要得到:

<div class="wrap"><div><div id="hmenus"><div class="nav mainnavs"><ul><li><a id="nav-questions" href="/questions">Questions</a></li><li><a id="nav-tags" href="/tags">Tags</a></li><li><a id="nav-users" href="/users">Users</a></li><li><a id="nav-badges" href="/badges">Badges</a></li><li><a id="nav-unanswered" href="/unanswered">Unanswered</a></li></ul></div></div></div></div>

3
我需要这个 - 一些电子邮件客户端存在块元素之间空格的错误。因为我在部署前清理HTML,所以我需要一种方法来解决这个问题。@Czechnology 的正则表达式模式完美地解决了这个问题- https://dev59.com/K2435IYBdhLWcg3wigkk#5362207。 - Dan Blows
6
当人们说“这有什么意义”时,我也会好奇!但总会有一个原因。请注意,我的任务是翻译文本并使其更通俗易懂,不提供解释或额外的信息。 - Mbarry
2
我很惊讶没有人提出这种解决内联块问题的方法,当元素之间存在空格时会导致问题(通常在网格系统中,但也可能在其他地方)。我还没有尝试过这个方法,但我来到这里是为了寻找一个替代 <div class="box">...</div><!-- [\n] --><div class="box"> 的源代码。 - James S
我需要这个来编写针对我的代码的测试 - 我正在重构,空格可能会改变 - 我需要测试内容而不是空格。 - ErichBSchulz
15个回答

53

$html = preg_replace('~>\s+<~', '><', $html);

这行代码使用PHP的preg_replace函数,用"><"替换了"> <"。这可以帮助减小数据大小,但也有更好的选项可供选择。


4
在没有其他人看到任何意义的地方,有人在超越常规思维之外看到了许多点……:D 这个正则表达式对我来说非常完美。 - Max Kielland
21
遗憾的是,这会将<b>Hello</b> <i>world</i>更改为<b>Hello</b><i>world</i>。检测空格是否有意义几乎是不可能的(列出一些内联和块级元素的列表会很方便)。 - Salman A
1
@SalmanA是正确的 - 你需要非常小心这个正则表达式,因为有一些情况下你不想删除标签之间的空格。这可能出现在<pre> <code> <textarea> <script>内部。除非制表符位于两个标签之间,否则此模式也无法捕获插入文本内容中的大量空格/制表符。 - Simon East
1
@Simon,这个正则表达式完全符合OP所要求的:“删除标签之间的空格”。显然,这可能不是所有用途的最佳行为,但这取决于OP。 - Czechnology
1
是的,它可能非常适合楼主的情况,这很好。但我认为对于那些像我一样谷歌搜索“从HTML中删除空格”的人来说,这是一个重要的免责声明。 - Simon East
显示剩余8条评论

13

这个问题被提出已经有一段时间了,但我仍然认为有必要发布这个答案来帮助遇到同样问题的人。

对于我来说,这些解决方案都不可行,因此我想出了这个解决方案: 使用output_buffer

函数ob_start接受一个回调函数作为参数,该回调函数在输出整个字符串之前应用于整个字符串。 因此,如果在刷新输出之前从字符串中删除空格,则完成了。

/** 
 * Remove multiple spaces from the buffer.
 * 
 * @var string $buffer
 * @return string
 */
function removeWhitespace($buffer)
{
    return preg_replace('/\s+/', ' ', $buffer);
}

ob_start('removeWhitespace');

<!DOCTYPE html>
<html>
    <head></head>
    <body></body>
</html>

ob_get_flush();

以上内容将会打印出类似以下的输出:

<!DOCTYPE html> <html> <head> </head> <body> </body> </html>

希望这有所帮助。

如何在面向对象编程中使用它

如果您在PHP中使用面向对象的代码,您可能想要使用一个位于对象内部的回调函数。

如果您有一个名为,例如HTML的类,您必须使用此代码行

ob_start(["HTML","removeWhitespace"]); 

2
Savas,这样做会移除您所需要的空格吗? 说:<div>我需要在这里留出空白。</div> <div>在此div之前有一个空格需要移除。</div> - Jomar Sevillejo
1
@Jomar:不,它会将多个空格字符的序列折叠成一个空格。这个答案中的示例输出是不正确的;它应该是 <!DOCTYPE html> <html> <head></head> <body></body> </html> - Zilk
1
@JomarSevillejo 不好意思,我的错,我已经按照Zilk的要求更新了输出。 - Savas Vedova

5

如果还有人需要,我从@Martin Angelova和@Savas Vedova的回答中整合了一个函数,解决了我的问题,代码如下:

<?php 
   function rmspace($buffer){ 
        return preg_replace('~>\s*\n\s*<~', '><', $buffer); 
   };
?>
<?php ob_start("rmspace");  ?>
   //Content goes in here 
<?php ob_end_flush(); ?>

注意:我没有在生产环境中测试性能惩罚。

1
相当快的正则表达式,我使用它。 - electroid

4

可以使用正则表达式替换来解决问题,例如:

$result = preg_replace('!\s+!smi', ' ', $content);

你使用的三个模式修饰符都是不必要的。 - Gumbo
真的,是我的错,请查看其他答案以获取解决方案。 - laander

3
$html = preg_replace('~>\s*\n\s*<~', '><', $html);

我认为这是解决 <b>Hello</b> <i>world</i> 问题的方法。思路是仅在有新行时删除空格。它适用于常见的HTML语法,例如:

<div class="wrap">
    <div>
    </div>
</div>

同时: $html = preg_replace('>\s+<', '> <', $html); - Gershom Maes

2
作为 gpupo 的帖子,提供了许多不同类型的间距格式的最干净的解决方案。然而,在结尾处忘记了一个小但很重要的部分!最后一个字符串修剪 :-p 下面是一个经过测试和工作的解决方案。
function compress_html($content)
{
    $i       = 0;
    $content = preg_replace('~>\s+<~', '><', $content);
    $content = preg_replace('/\s\s+/',  ' ', $content);

    while ($i < 5)
    {
        $content = str_replace('  ', ' ', $content);
        $i++;
    }

    return trim($content);
}

2
< p > 数组 reduce 函数:

$html = explode("\n", $html);
function trimArray($returner, $value) {
    $returner .= trim($value);
    return $returner;
}
echo $html = array_reduce($html, 'trimArray');

2

感谢您发布这个问题。问题确实涉及某些环境中的空格错误。虽然正则表达式解决方案适用于一般情况,但为了快速修补,请删除前导空格并在每行末尾添加 <br> 标记。PHP会删除紧随闭合 ?> 后的换行符。例如:

<ul><?php ?>
<li><a id="nav-questions" href="/questions">Questions</a></li><?php ?>
<li><a id="nav-tags" href="/tags">Tags</a></li><?php ?>
<li><a id="nav-users" href="/users">Users</a></li><?php ?>
<li><a id="nav-badges" href="/badges">Badges</a></li><?php ?>
<li><a id="nav-unanswered" href="/unanswered">Unanswered</a></li><?php ?>
</ul>

显然这种方法在多种情况下都不是最优的,但对于一个局部问题而言,它可以工作而不影响整个工具链。


1
如果你使用了8位ASCII码,它将会移除它们并保留在128-255范围内的字符。
 $text = preg_replace('/[\x00-\x1F\xFF]/', " ", $text );

如果您有一个UTF-8编码的字符串,它会起到作用。
$text = preg_replace('/[\x00-\x1F\x7F]/u', '', $text);

如果需要更多信息,可以访问以下链接more information


1
//...
public function compressHtml($content)
{
    $content = preg_replace('~>\s+<~', '><', $content);
    $content = preg_replace('/\s\s+/', ' ', $content);
    $i = 0;
    while ($i < 5) {
        $content = str_replace('  ', ' ', $content);
        $i++;    
    }

    return $content;
}

已测试,这就是解决方案!请查看我的下面版本,针对返回值忘记进行完整字符串修剪进行了微小更新。 - tfont

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接