我正在尝试通过令牌拆分HTML字符串,以便在不显示完整帖子的情况下创建博客预览。它比我最初想的还要更难。以下是问题:
read_more()
可以
放在字符串中的任何位置,
包括嵌套在一个
段标记。可能的用途示例:
<p>Some text here. read_more()</p>
<p>Some text read more() here.</p>
<p>read_more()</p>
<p> read_more()</p>
read_more()
到目前为止,我已尝试在令牌上拆分字符串,但它会留下无效的HTML。正则表达式可能是另一种选择。您将采用什么策略来解决这个问题并使其尽可能防弹?任何代码片段或提示也将受到赞赏(我正在使用PHP)。
答案 0 :(得分:2)
function stripmore($in)
{
list($p1,$p2) = explode("read_more()",$in,2);
$pass1 = preg_replace("~>[^<>]+<~","><",$p2);
$pass2 = preg_replace("~^[^<>]+~","",$pass1);
$pass3 = null;
while ( $pass3 != $pass2 )
{
if ( $pass3 !== null ) $pass2 = $pass3;
$pass3 = preg_replace("~<([^<>]+)></\\1>~","",$pass2);
}
return $p1."read_more()".$pass3;
}
这会在read_more()标记之后删除任何非html,并通过剥离相应的标记将其减少到最小值,同时保持任何标记在标记之前和结束之后开始:
<p>Some text here. read_more()</p>
==> <p>Some text here. read_more()</p>
<p>Some <b>text</b> read_more() <b>here</b>.</p>
==> <p>Some <b>text</b> read_more()</p>
<p>Some <b>text read_more() here</b>.</p>
==> <p>Some <b>text read_more()</b></p>
答案 1 :(得分:1)
我目前看到的唯一正确选项是在PHP中编写自己的无上下文语法HTML解析器,这将允许您适当地关闭标记(只需通过在读取更多()时弹出堆栈,并为每个pop添加关闭标签)。
然而,这是很多工作,这可能适合你:
$stripped = strip_tags($input);
list($preview) = explode("read more()", $stripped);
您丢失了HTML标记,但它很容易实现。首页上没有可能的XSS:)
答案 2 :(得分:1)
为什么不使用可以生成HTML的许多标记语言中的一种,而不是要求您关闭标记等,而不是使用完整的HTML。这将更容易培训您的用户,并将避免所有接受原始HTML的XSS攻击的可能性允许。
PHP Markdown似乎显然是合适的,特别是考虑到你想要避免使用GNU GPL。
答案 3 :(得分:1)
为了回答对我的评论的评论,我决定让它成为一个答案,所以我可以利用标记选项。
为什么你不能在结果字符串上使用trim(),找到缺少的open或close元素并适当追加,以使其成为有效的HTML?
只需前后移动即可查找下一个打开/关闭元素,并修复HTML。
所以,你可以在字符串中向前和向后走,以获得下一个<
和>
,如果这是一个HTML元素,那么就停在那里,否则继续前进。
理想情况下,每次提交都需要处理一次,因此您需要为此操作付出代价。
<强>更新强>
我忘了提供帮助strpos
的链接:
答案 4 :(得分:1)
PHP整理是一个非常轻量级和高效的实用程序来修复无效标签。 看看,我已经使用过它并在我的应用程序中对它进行了基准测试,效果很好。 此外,它有许多配置选项,以满足您的需求,并处理其他可能的问题,如编码,嵌套无效标签等。
参见参考资料: http://www.php.net/manual/en/tidy.cleanrepair.php
示例用法:
<?php
function tidyString($str)
{
$config = array('show-body-only' => true); /* else it adds HTML tags too */
tidy_set_encoding('utf8');
$outStr = tidy_repair_string($str,$config);
return $outStr;
}
$inStr = "<span> this is my incorrect html</spa";
echo tidyString($inStr); // Output : <span>this is my incorrect html</span>
?>
答案 5 :(得分:0)
为什么不使用两个textareas?一个在切割上方和下方?应该让用户明白发生了什么,并为您消除头痛。
如果你做想要使用令牌,你应该选择更有特色的东西。也许:<!--full body cut-->
你可以更确定一点,实际上并没有将内容误认为令牌。
无论如何,如果你想在令牌上拆分字符串,你只需要使用strpos()
找出令牌 的位置,然后使用substr()
来切断第一部分。类似的东西:
$intro = substr($text, 0, strpos($string, $token));
然后,将$intro
到tidy(PHP扩展名)运行到clean up the syntax,然后剥去它添加的额外垃圾。 (我认为你可以使用空字符串str_replace()附加内容。)