将HTML字符串拆分为两个字符串,而无需切分单词并在PHP中保留HTML

将HTML字符串拆分为两个字符串,而无需切分单词并在PHP中保留HTML,php,regex,string,Php,Regex,String,我正在寻找一种将包含HTML的字符串拆分为两半的方法。要求: 按字符数拆分字符串 不能在单词的中间分裂 在计算拆分字符串的位置时,不能包含HTML字符 例如,以以下字符串为例: 这是一个包含HTML标记和文本内容的测试字符串。这个字符串需要被分割而不通过一个词的中间部分,并且必须保持HTML的有效性,即不在标签的中间分裂,并且确保正确地关闭结束标签。 < /Cord>< /P> 假设我想在字符位置39拆分,在单词HTML(不包括HTML)的中间,我想让函数将字符串拆分为以下两部分: 这是一个

我正在寻找一种将包含HTML的字符串拆分为两半的方法。要求:

  • 按字符数拆分字符串
  • 不能在单词的中间分裂
  • 在计算拆分字符串的位置时,不能包含HTML字符
例如,以以下字符串为例:

这是一个包含HTML标记和文本内容的测试字符串。这个字符串需要被分割而不通过一个词的中间部分,并且必须保持HTML的有效性,即不在标签的中间分裂,并且确保正确地关闭结束标签。

< /Cord>< /P> 假设我想在字符位置39拆分,在单词HTML(不包括HTML)的中间,我想让函数将字符串拆分为以下两部分:

这是一个测试字符串,包含HTML

标签和文本内容。这个字符串需要被分割而不通过一个词的中间部分,并且必须保持HTML的有效性,即不在标签的中间分裂,并且确保正确地关闭结束标签。

< /Cord>< /P> 注意,在上面的两个示例结果中,我要求遵守HTML有效性,因此添加了结束标记

。另外,在后半部分添加了一个起始标记,作为在字符串末尾关闭的标记

我在StackOverflow上找到了这个函数,它可以将字符串截断若干个文本字符并保留HTML,但它只达到了我所需要的一半,因为我需要将字符串分成两半

function printTruncated($maxLength, $html)
{
    $printedLength = 0;
    $position = 0;
    $tags = array();

    while ($printedLength < $maxLength && preg_match('{</?([a-z]+)[^>]*>|&#?[a-zA-Z0-9]+;}', $html, $match, PREG_OFFSET_CAPTURE, $position))
    {
        list($tag, $tagPosition) = $match[0];

        // Print text leading up to the tag.
        $str = substr($html, $position, $tagPosition - $position);
        if ($printedLength + strlen($str) > $maxLength)
        {
            print(substr($str, 0, $maxLength - $printedLength));
            $printedLength = $maxLength;
            break;
        }

        print($str);
        $printedLength += strlen($str);

        if ($tag[0] == '&')
        {
            // Handle the entity.
            print($tag);
            $printedLength++;
        }
        else
        {
            // Handle the tag.
            $tagName = $match[1][0];
            if ($tag[1] == '/')
            {
                // This is a closing tag.

                $openingTag = array_pop($tags);
                assert($openingTag == $tagName); // check that tags are properly nested.

                print($tag);
            }
            else if ($tag[strlen($tag) - 2] == '/')
            {
                // Self-closing tag.
                print($tag);
            }
            else
            {
                // Opening tag.
                print($tag);
                $tags[] = $tagName;
            }
        }

        // Continue after the tag.
        $position = $tagPosition + strlen($tag);
    }

    // Print any remaining text.
    if ($printedLength < $maxLength && $position < strlen($html))
        print(substr($html, $position, $maxLength - $printedLength));

    // Close any open tags.
    while (!empty($tags))
        printf('</%s>', array_pop($tags));
}
函数printTruncated($maxLength,$html)
{
$printedLength=0;
$position=0;
$tags=array();
而($printedLength<$maxLength&&preg#u match('{]*>|&#?[a-zA-Z0-9]+}',$html,$match,preg#u OFFSET#u CAPTURE,$position))
{
列表($tag,$tagPosition)=$match[0];
//打印指向标记的文本。
$str=substr($html,$position,$tagPosition-$position);
如果($printedLength+strlen($str)>$maxLength)
{
打印(substr($str,0,$maxLength-$printedLength));
$printedLength=$maxLength;
打破
}
印刷品($str);
$printedLength+=strlen($str);
如果($tag[0]='&'))
{
//处理实体。
打印($tag);
$printedLength++;
}
其他的
{
//处理标签。
$tagName=$match[1][0];
如果($tag[1]=='/'))
{
//这是一个结束标记。
$openingTag=array\u pop($tags);
assert($openingTag==$tagName);//检查标记是否正确嵌套。
打印($tag);
}
else if($tag[strlen($tag)-2]=='/'))
{
//自动关闭标签。
打印($tag);
}
其他的
{
//开场白。
打印($tag);
$tags[]=$tagName;
}
}
//在标记之后继续。
$position=$tagPosition+strlen($tag);
}
//打印任何剩余文本。
如果($printedLength<$maxLength&&$position
几乎所有其他答案都会引用的一般规则是“不要使用正则表达式处理HTML-您无法捕获所有边缘情况”

我相信这是真的

字符串中的任何内容,即使是格式稍有错误的,甚至是最好的正则表达式,都会把它搞砸

忽略你想要拆分一些标签而不是其他标签(P标签是标签,毕竟你想把一个分割成两个),你可能需要重新思考这个过程,并且对你想要达到的目标非常具体,例如在段落标签的中间是分裂的,好吗?那divs呢?如果中间点在标记内,您希望第一个字符串更长,还是第二个字符串更长

假设拆分段落标记是可以的,但其他的则不行,请尝试以下方法:(这里没有复制粘贴代码,抱歉) *剥离目标字符串两次-一次剥离所有标记,一次剥离段落标记 *在“无标记”字符串中找到中间点 *在中间点后的第一个空格处拆分所有字符串的无标记 *在just-p-tags-stripped字符串中找到与上一步中点后的单词匹配的位置-这应该告诉您忽略标记时just-p-tags-stripped字符串中的“中间”位置 *检查是否在标签内

。。事实上,当我说到这一点的时候,我意识到我写的90%都是非常明显的,最后一点就是问题所在

我将在这里留下我半成品的咆哮,以警告其他人和我自己。

给出的答案也适用于你的问题