当前位置: 首页 > 面试题库 >

截断包含HTML的文本,忽略标签

欧渝
2023-03-14
问题内容

我想截断一些文本(从数据库或文本文件加载),但其中包含HTML,因此包含了标签,并且将返回较少的文本。然后,这可能导致标签未关闭或部分关闭(因此Tidy可能无法正常工作,并且内容仍然较少)。我如何基于文本截断(并且可能在到达表时停止,因为这可能会导致更复杂的问题)。

substr("Hello, my <strong>name</strong> is <em>Sam</em>. I&acute;m a web developer.",0,26)."..."

将导致:

Hello, my <strong>name</st...

我想要的是:

Hello, my <strong>name</strong> is <em>Sam</em>. I&acute;m...

我怎样才能做到这一点?

虽然我的问题是有关如何在PHP中进行操作,但最好知道如何在C#中进行操作…要么应该可以,因为我认为我可以将方法移植过来(除非它是内置的)方法)。

还要注意,我包括了一个HTML实体&acute;-必须将其视为单个字符(而不是本示例中的7个字符)。

strip_tags 是一个备用,但我会丢失格式和链接,并且HTML实体仍然会出现问题。


问题答案:

假设您使用的是有效的XHTML,则解析HTML并确保正确处理标签非常简单。您只需要跟踪到目前为止已打开的标签,并确保“在您出门时”再次将其关闭。

<?php
header('Content-type: text/plain; charset=utf-8');

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

    // For UTF-8, we need to count multibyte sequences as one character.
    $re = $isUtf8
        ? '{</?([a-z]+)[^>]*>|&#?[a-zA-Z0-9]+;|[\x80-\xFF][\x80-\xBF]*}'
        : '{</?([a-z]+)[^>]*>|&#?[a-zA-Z0-9]+;}';

    while ($printedLength < $maxLength && preg_match($re, $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 ($printedLength >= $maxLength) break;

        if ($tag[0] == '&' || ord($tag) >= 0x80)
        {
            // Pass the entity or UTF-8 multibyte sequence through unchanged.
            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(10, '<b>&lt;Hello&gt;</b> <img src="world.png" alt="" /> world!"); print("\n");

printTruncated(10, '<table><tr><td>Heck, </td><td>throw</td></tr><tr><td>in a</td><td>table</td></tr></table>'); print("\n");

printTruncated(10, "<em><b>Hello</b>&#20;w\xC3\xB8rld!</em>"); print("\n");

编码说明
:上面的代码假定XHTML是UTF-8编码的。还支持ASCII兼容的单字节编码,只需将其false作为第三个参数传递即可。不支持其他多字节编码,尽管您可能会mb_convert_encoding在调用该函数之前先转换为UTF-8,然后在每个print语句中再次转换回去,从而获得支持。

(不过,您应该 始终 使用UTF-8。)

编辑 :更新为处理字符实体和UTF-8。修复了以下错误:如果该字符是一个字符实体,该函数将打印一个字符过多。



 类似资料:
  • 有人能帮帮我吗?

  • 问题内容: 我刚刚开始将Swing应用程序从OS X移植到Windows,使用s会很麻烦。 我注意到,如果标签的文本是HTML ,则指定为的字体将被忽略(在Mac上不会发生)。HTML格式极其有用,可提高复杂显示的可读性。 通常情况下,我会在HTML标记中指定字体,但是我使用的字体是在运行时通过JAR中的ttf 加载的。我尝试在font标签中使用加载的字体的名称,但这没有用。 有什么办法可以在Wi

  • 问题内容: 我最近看到了很多用于在HTML页面中搜索和突出显示术语的库。但是,我看到的每个库都存在相同的问题,它们找不到部分用html标记封装的文本,并且/或者找不到包含&表示的特殊字符。 示例a: 搜索“测试”将找到第一个实例,但找不到第二个实例。 示例b: 搜索“lápices”或“ lapices”将不会产生结果。 有没有这样做的JS库,或者至少是一种避免这些障碍的方法? 提前致谢! 问题答

  • 问题内容: 如何 忽略 此preg_replace中的 html标签 。我有一个foreach函数来进行搜索,因此,如果有人搜索“苹果范围”,则preg_replace也会将范围应用于范围,并且html会中断: 提前致谢! 问题答案: 我假设您应该基于DOMDocument和DOMXPath而不是使用正则表达式来创建函数。即使那些功能非常强大,您也会遇到像您描述的问题那样的问题,这些问题不是(总是

  • 问题内容: 我正在尝试获取HTML文档中包含以下文本模式的元素:#\ S {11} 因此,前者将通过使用以下内容进行匹配: 结果将是这样的: 我可以获取所有匹配的文本(请参见上面的行)。但是我希望文本的父元素匹配,因此我可以将其用作遍历文档树的起点。在这种情况下,我希望所有h2元素都返回,而不是文本匹配。 有想法吗? 问题答案: 印刷品:

  • #include <stdio.h> int main(void) { int i = 0; int sum = 0; for (i = 1; i <= 200; i++) { sum += i; } printf("%d\n", sum); return