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

时间:2012-01-10 12:26:41

标签: php xml parsing text replace

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

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

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

  2. 我需要提取所有纯文本,这样我就可以在最后创建不包含图像标签或半标签(或前面的代码片段)的摘录。

    < / LI>

    我认为我使用以下代码解决了问题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子项的方法但是我找不到如何检查元素是ap,ul还是ol。

    我找不到解决问题1的方法,因为我不知道如何替换XML对象中的内容,但保留其他所有内容。 (或者我错过了一些完全明显的东西?)

1 个答案:

答案 0 :(得分:0)

经过大量搜索后,我无法找到使用XML解析的确切内容,除此之外我还需要其他一些功能。我解决了REGEX的问题,因为所有的HTML都是由我生成的。

因此,此处提供的解决方案解决了我原有问题的问题+更多。

此函数接受一段内容(字符串)并返回几个字符串:

  • md =与pre里面的anglebrackets更改为他们的html实体的内容相同(我关于HTML的博客,但在我的编辑帖子屏幕中我不希望html里面的pre被解析
  • html = pre pre的所有内容都是Markdown'd,pre的内部的每个htmlchar都更改为他们的html实体。
  • 摘录=文字缩小了近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;
    }