首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >strtok()的问题

strtok()的问题
EN

Stack Overflow用户
提问于 2011-10-11 04:19:25
回答 1查看 916关注 0票数 1

我和这个搏斗已经有一段时间了。我知道这是很多代码要看,但我不知道问题的所在,似乎不能缩小它。我会赏金的。

我编写这个类是为了解析bbcode。它主要使用strtok(),除非您将两个标记放在一起,否则类工作得很好,而且我无法在我的一生中找出原因。

例如,[b] [i]test1[/i] [/b]会导致<strong> <em>test1</em> </strong>。然而,[b][i]test1[/i][/b]导致了<strong>i]test1/b]</strong>。最后一个</strong>标记仅在其中,因为解析器自动关闭在字符串中找不到结束标记的标记。它在某种程度上完全忽略了[i][/b]标记。

这是类以及它用于设置各种bbcode的一个子类。子类基本上只是一个没有行为的数据结构。

代码语言:javascript
复制
<?php
    // beware images can contain any url/any get request. beware of csrf
    class Lev_TextProcessor_Extension_BbCode {

        protected $elements = array();
        protected $openTags = array();

        public function __construct() {
            $this->elements['b'] = new Lev_TextProcessor_Extension_BbCode_Element('<strong>', '</strong>');
            $this->elements['i'] = new Lev_TextProcessor_Extension_BbCode_Element('<em>', '</em>');
            $this->elements['u'] = new Lev_TextProcessor_Extension_BbCode_Element('<span style="text-decoration: underline;">', '</span>');
            $this->elements['s'] = new Lev_TextProcessor_Extension_BbCode_Element('<span style="text-decoration: line-through;">', '</span>');
            $this->elements['size'] = new Lev_TextProcessor_Extension_BbCode_Element('<span style="font-size: ', '</span>', 'px;">');
            $this->elements['color'] = new Lev_TextProcessor_Extension_BbCode_Element('<span style="color: ', '</span>', ';">');
            $this->elements['center'] = new Lev_TextProcessor_Extension_BbCode_Element('<div style="text-align: center;">', '</div>', '', true, true, false);
            $this->elements['url'] = new Lev_TextProcessor_Extension_BbCode_Element('<a href="', '</a>', '">');
            $this->elements['email'] = new Lev_TextProcessor_Extension_BbCode_Element('<a href="mailto:', '</a>', '">');
            $this->elements['img'] = new Lev_TextProcessor_Extension_BbCode_Element('<img src="', '" alt="" />', '', false, false, true);
            $this->elements['youtube'] = new Lev_TextProcessor_Extension_BbCode_Element('<object width="400" height="325"><param name="movie" value="http://www.youtube.com/v/{param}"></param><embed src="http://www.youtube.com/v/', '" type="application/x-shockwave-flash" width="400" height="325"></embed></object>', '', false, false, false);
            $this->elements['code'] = new Lev_TextProcessor_Extension_BbCode_Element('<pre><code>', '</code></pre>', '', true, false, false);
        }

        public function processText($input) {
            // pre processing
            $input = htmlspecialchars($input, ENT_NOQUOTES);
            $input = nl2br($input);
            $input = str_replace(array("\n", "\r"), '', $input);
            // start main processing
            $output = '';
            $allow_child_tags = true;
            $allow_child_quotes = true;

            $string_segment = strtok($input, '[');

            do {
                // check content for quotes
                if ($allow_child_quotes === false) {
                    if (strpos($string_segment, '"') === false) {
                        $output .= $string_segment;
                    }
                } else {
                    // add content to output
                    $output .= $string_segment;
                }

                $tag_contents = strtok(']');

                if (strpos($tag_contents, '/') === 0) {
                    // closing tag
                    $tag = substr($tag_contents, 1);
                    if (isset($this->elements[$tag]) === true && array_search($tag, $this->openTags) !== false) {
                        // tag found
                        do {
                            // close tags till matching tag found
                            $last_open_tag = array_pop($this->openTags);
                            $output .= $this->elements[$last_open_tag]->htmlAfter;
                        } while ($last_open_tag !== $tag);
                        $allow_child_tags = true;
                        $allow_child_quotes = true;
                    }
                } else {
                    // opening tag
                    // separate tag name from argument if there is one
                    $equal_pos = strpos($tag_contents, '=');
                    if ($equal_pos === false) {
                        $tag_name = $tag_contents;
                    } else {
                        $tag_name = substr($tag_contents, 0, $equal_pos);
                        $tag_argument = substr($tag_contents, $equal_pos + 1);
                    }
                    if (isset($this->elements[$tag_name]) === true) {
                        // tag found
                        if (($this->elements[$tag_name]->allowParentTags === true || count($this->openTags) === 0) && $allow_child_tags === true) {
                            // add tag to open tag list and set flags
                            $this->openTags[] = $tag_name;
                            $allow_child_tags = $this->elements[$tag_name]->allowChildTags;
                            $allow_child_quotes = $this->elements[$tag_name]->allowChildQuotes;
                            $output .= $this->elements[$tag_name]->htmlBefore;
                            // if argument exists
                            if ($equal_pos !== false) {
                                if (strpos($tag_argument, '"') === false) {
                                    $output .= $tag_argument;
                                }
                                $output .= $this->elements[$tag_name]->htmlCenter;
                            }
                        }
                    }
                }

                $string_segment = strtok('[');
            } while ($string_segment !== false);
            // close left over tags
            while ($tag = array_pop($this->openTags)) {
                $output .= $this->elements[$tag]->htmlAfter;
            }
            return $output;
        }
    }
?>

<?php

    class Lev_TextProcessor_Extension_BbCode_Element {

        public $htmlBefore;
        public $htmlAfter;
        public $htmlCenter;
        public $allowChildQuotes;
        public $allowChildTags;
        public $allowParentTags;

        public function __construct($html_before, $html_after, $html_center = '', $allow_child_quotes = true, $allow_child_tags = true, $allow_parent_tags = true) {
            if ($allow_child_quotes === false && $allow_child_tags === true) throw new Lev_TextProcessor_Exception('You may not allow child tags if you do not allow child quotes.');
            $this->htmlBefore = $html_before;
            $this->htmlAfter = $html_after;
            $this->htmlCenter = $html_center;
            $this->allowChildQuotes = $allow_child_quotes;
            $this->allowChildTags = $allow_child_tags;
            $this->allowParentTags = $allow_parent_tags;
        }
    }
?>

编辑

通过创建用于令牌化的以下类进行修正。

代码语言:javascript
复制
<?php

    // unlike PHP's strtok() function, this class will not skip over empty tokens.
    class Lev_TextProcessor_Tokenizer {

        protected $string;

        public function __construct($string) {
            $this->string = $string;
        }

        public function getToken($token) {
            $segment_length = strcspn($this->string, $token);
            $token = substr($this->string, 0, $segment_length);
            $this->string = substr($this->string, $segment_length + 1);
            return $token;
        }
    }
?>
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-10-11 19:19:05

虽然我不认为这是真正的解决办法,但这似乎是我要阐明我的观点的唯一方法。

它可能与strtok()的工作方式有关,可以得到您想要的结果。

虽然不完美,但我能够获得接近您预期的结果:

代码语言:javascript
复制
 <?
 $data1 = strtok('[b][i]test1[/i][/b]','[');
 $data2 = strtok(']');
 $data3 = strtok('[');
 $data4 = strtok(']');
 $data5 = strtok('[');
 $data6 = strtok(']');
 var_dump($data1, $data2,$data3, $data4, $data5, $data6);
 /*
  OUTPUT
    string(2) "b]"
    string(1) "i"
    string(5) "test1"
    string(2) "/i"
    string(3) "/b]"
    bool(false)
 * /
 ?>

正如我所说的,这并不完美,但也许看到这一点将有助于您在处理此解决方案的过程中。我个人从未用这种类型的解析来处理BBCode,而是使用preg_match()

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7721331

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档