1

给定一个像这样的 HTML 字符串:

Lorem ipsum dolor sit amet, <a href="#">consectetuer adipiscing</a>
elit, <strong>tincidunt</strong> ut volutpat.

我如何用<span>元素包围所有单词,所以它变成:

<span>Lorem</span> <span>ipsum</span> <span>dolor</span> <span>sit</span>
<span>amet,</span> <a href="#"><span>consectetuer</span> <span>adipiscing</span></a>
<span>elit,</span> <strong><span>tincidunt</span></strong> <span>ut</span>
<span>volutpat.</span>
4

3 回答 3

3

更简单的方法

preg_replace('([a-zA-Z.,!?0-9]+(?![^<]*>))', '<span>$0</span>', '{{your data}}');

它包含<span>您词汇表中的所有单词,[a-zA-Z.,!?0-9]+除了<brackets>.
现在,如果需要,更改您的词汇表似乎很容易,例如,如果您不希望单个标点符号被包围,等等。

于 2012-08-10T14:23:30.180 回答
1

我试过这个,认为这就是你要找的:

$result = preg_replace("/(<[^>]+>)?\\w*/us", "<span>$0</span>", $searchText);

这是输入

Lorem ipsum dolor sit amet, <a href="#">consectetuer adipiscing</a>elit, <strong>tincidunt</strong> ut volutpat.

这是输出

<span>Lorem</span> <span>ipsum</span> <span>dolor</span> <span>sit</span> <span>amet</span>, <span><a href="#">consectetuer</span> <span>adipiscing</span><span></a></span><span>elit</span>, <span><strong>tincidunt</span><span></strong></span> <span>ut</span> <span>volutpat</span>.
于 2012-08-10T14:39:24.477 回答
1

如果@daftcoder 的解决方案对您有用,那很好,但如果您的代码中有实体(< 等),它确实会失败。我找不到任何其他失败的案例。

如果这很重要,您可以在 PHP 中使用 DOM 操作。我知道这要复杂得多,但它应该比简单的正则表达式在更多情况下工作。

walk 和 doReplace 函数从另一个问题的答案从 JS 转换为 PHP。(用 SPAN 标签包围 HTML 文本中的单个单词?

<?php

echo wrap_words('span', 'Lorem ipsum dolor sit amet, <a href="#">consectetuer adipiscing</a> elit, <strong>tincidunt</strong> ut volutpat.');

function wrap_words($tag, $text) {
    $document = new DOMDocument();
    $fragment = $document->createDocumentFragment();
    $fragment->appendXml($text);
    walk($tag, $fragment);
    $html = $document->saveHtml($fragment);
    // using saveHTML with a documentFragment can leave an invalid "<>"
    // at the beginning of the string - remove it
    return preg_replace('/^<>/', '', $html);
}

function walk($tag, $root)
{
    if ($root->nodeType == XML_TEXT_NODE)
    {
        doReplace($tag, $root);
        return;
    }
    $children = $root->childNodes;
    for ($i = $children->length - 1; $i >= 0; $i--)
    {
        walk($tag, $children->item($i));
    }
}

function doReplace($tag, $text)
{
    $fragment = $text->ownerDocument->createDocumentFragment();
    $fragment->appendXML(preg_replace('/\S+/', "<{$tag}>\$0</{$tag}>", $text->nodeValue));
    $parent = $text->parentNode;
    $children = $fragment->childNodes;
    for ($i = $children->length - 1; $i >= 0; $i--)
    {
        $parent->insertBefore($children->item($i), $text->nextSibling);
    }
    $parent->removeChild($text);
}
于 2012-08-10T16:00:02.730 回答