我正在用PHP写我自己的博客,我想能够在Markdown中写帖子,用HTML显示结果,我还需要用HTML做一些自定义的事情。
有一个简单的脚本可以将Markdown转换为HTML,但一旦完成,我需要对HTML做一些事情:
-
我需要使用htmlenties()函数替换pre标记中的所有HTML符号。(在我的博客中,我发布了包括HTML在内的代码,我只想显示这个HTML,而不是在浏览器中解析它)。
-
我需要提取所有的纯文本,这样我就可以在最后创建不包括图像标签或半标签(或者pre中的代码片段)的摘录。
我认为我已经通过使用以下代码解决了问题2:
$xml = new SimpleXMLElement('<xml>' . $html . '</xml>');
$xml现在看起来像:
<xml>
<p>some random text</p>
<img src='image.jpg'>
<p>some random text</p>
</xml>
这将提取所有文本:
foreach($xml->{'p'} as $p){
echo $p . '<hr>';
}
这是可行的,但我也希望它包括在ul和ol中找到的所有文本(按照它们在XML中出现的顺序)。我已经搜索了一种方法来循环$XML的所有子元素,但我找不到如何检查元素是p、ul还是ol。
我找不到解决问题1的方法,因为我不知道如何替换XML对象中的内容,但保留其他所有内容。(或者我遗漏了一些非常明显的东西?)
经过大量搜索,我无法使用XML解析找到我想要的东西,此外我还需要一些其他功能。我解决了REGEX的问题,因为所有的HTML都是由我生成的。
所以这里提供的解决方案解决了我原来的问题+更多的问题。
此函数获取一段内容(字符串)并返回几个字符串:
- md=与pre中带尖括号的内容更改为它们的html实体相同(我写了关于html的博客,但在编辑文章屏幕中,我不希望pre中的html被解析
- html=pre之外的所有内容都被标记,pre内部的每个htmlchar都被更改为它们的html实体
- extraction=文本压缩了近300个字符,没有任何预标记(或其内容),没有markdown语法或html标记
-
meta=与160个字符的摘录相同。
function prepareContent($content) { // I use this instead of htmlentities for the plain text, this prevents HTML to be parsed inside the edit screen // all HTML is served with htmlentities instead function removeAngleBrackets($str) { $str = str_replace('<','<',$str); $str = str_replace('>','>',$str); return $str; } $segments = preg_split('/(<'/?pre.*?>)/', $content, -1, PREG_SPLIT_DELIM_CAPTURE); // STATE MACHINE // borrowed from: http://stackoverflow.com/questions/1278491/howto-encode-texts-outside-the-pre-pre-tag-with-htmlentities-php#answer-1278575 // this breaks when I nest pre's in pre's (unless I escape the <pre> myself), could be fixed though // $state = 0 if outside of a pre // $state = 1 if inside of a pre $state = 0; $plaintext = ''; $html = ''; $preless = ''; // $html, $plaintext and $preless are all written in here foreach ($segments as &$segment) { if ($state == 0) { if (preg_match('#<pre[^>]*>#i',$segment)) { //this is the pre opening tag $state = 1; $html .= $segment; $plaintext .= $segment; } else { //this is outside the pre tag $plaintext .= $segment; $markdown = Markdown($segment); $html .= $markdown; $preless .= $markdown; } } else if ($state == 1) { if ($segment == '</pre>') { //this is the pre closing tag $state = 0; $html .= $segment; $plaintext .= $segment; } else { //this is inside the pre tag $plaintext .= removeAngleBrackets($segment); // first encode > to > so I can re encode it together with other chars // else we get double encoding like: $amp;gt; $enti = html_entity_decode($segment); $html .= htmlspecialchars($enti, ENT_QUOTES); } } } $arr['html'] = SmartyPants($html); $arr['md'] = $plaintext; // the excerpt & meta // remove all html tags (markdown is already converted to HTML) $tagless = strip_tags($preless); function shrinkText($str, $limit) { $strlen = strlen($str); if($strlen > $limit) { $pos = strpos($str, ' ', $limit); if($strlen > $pos) { $result = substr($str,0,$pos); } } return $result ? $result : $str; } // I need to smartypants the excerpt to $excerpt = shrinkText($tagless, 275) . ' (...)'; $arr['excerpt'] = SmartyPants($excerpt); $arr['meta'] = shrinkText($tagless, 160); return $arr; }