如何从XML中提取某些标记并用SimpleXML替换其他标记


How to extract certain tags and replace others from XML with SimpleXML

我正在用PHP写我自己的博客,我想能够在Markdown中写帖子,用HTML显示结果,我还需要用HTML做一些自定义的事情。

有一个简单的脚本可以将Markdown转换为HTML,但一旦完成,我需要对HTML做一些事情:

  1. 我需要使用htmlenties()函数替换pre标记中的所有HTML符号。(在我的博客中,我发布了包括HTML在内的代码,我只想显示这个HTML,而不是在浏览器中解析它)。

  2. 我需要提取所有的纯文本,这样我就可以在最后创建不包括图像标签或半标签(或者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('<','&lt;',$str);
            $str = str_replace('>','&gt;',$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 &gt; 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;
    }