将嵌套短代码转换为数组的正则表达式

问题描述 投票:0回答:1

我有以下 PHP 函数,可以转换短代码,例如

[column]
    [row]
        [column][/column]
    [/row]
[/column]

到嵌套数组

Array
(
    [0] => Array
        (
            [tag] => column
            [attributes] => Array
                (
                )

            [content] => Array
                (
                    [0] => Array
                        (
                            [tag] => row
                            [attributes] => Array
                                (
                                )

                            [content] => Array
                                (
                                    [0] => Array
                                        (
                                            [tag] => column
                                            [attributes] => Array
                                                (
                                                )

                                            [content] => 
                                        )

                                )

                        )

                )

        )

)

如果我有一个[列]作为子项,但如果我有多个列作为子项,则效果很好

[column]
    [row]
        [column][/column]
        [column][/column]
    [/row]
[/column]

然后它给了我不正确的嵌套数组,即

Array
(
    [0] => Array
        (
            [tag] => column
            [attributes] => Array
                (
                )

            [content] => Array
                (
                    [0] => Array
                        (
                            [tag] => row
                            [attributes] => Array
                                (
                                )

                            [content] => Array
                                (
                                    [0] => Array
                                        (
                                            [tag] => column
                                            [attributes] => Array
                                                (
                                                )

                                            [content] => 
                                        )

                                )

                        )

                )

        )

    [1] => Array
        (
            [tag] => column
            [attributes] => Array
                (
                )

            [content] => 
        )

这是我的 PHP 函数

protected function shortCodeToArray($inputString)
{
    $itemArray = [];
    $openingTag = '/\[(\w+)(?:\s+([^\]]*))?\](.*?)(\[\/\1\]|$)/s';
    preg_match_all($openingTag, $inputString, $matches, PREG_SET_ORDER);
    foreach ($matches as $match) {
        $tagName = $match[1];
        $paramString = isset($match[2]) ? $match[2] : '';
        $content = $match[3];
        $nestedShortcodes = $this->shortCodeToArray($content);
        $itemArray[] = [
            'tag' => $tagName,
            'attributes' => $this->parseShortcodeParameters($paramString),
            'content' => is_array($nestedShortcodes) && !empty($nestedShortcodes) ? $nestedShortcodes : $content,
        ];
    }
    return $itemArray;
}

protected function parseShortcodeParameters($paramString)
{
    $params = [];
    preg_match_all('/(\w+)\s*=\s*["\']([^"\']+)["\']/', $paramString, $matches);
    for ($i = 0; $i < count($matches[0]); $i++) {
        $paramName = $matches[1][$i];
        $paramValue = $matches[2][$i];
        $params[$paramName] = $paramValue;
    }
    return $params;
}

我哪里出错了?

php regex shortcode
1个回答
0
投票

将其转换为 HTML 标签并使用 DOM 解析器的想法怎么样?

$codes = <<<'CODES'
[column]
    [row]
        [column][/column]
        [column][/column]
    [/row]
[/column]
CODES;
$html = str_replace(['[', ']'], ['<', '>'], $codes);
libxml_use_internal_errors(true);
$dom = new \DOMDocument();
$dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
echo $dom->saveHTML();

输出

<column>
    <row>
        <column></column>
        <column></column>
    </row>
</column>

现在你可以按照你想要的方式遍历 DOMDocument,甚至以简单的方式进行操作。

foreach($dom->getElementsByTagName('row') as $row) {
    foreach($row->getElementsByTagName('column') as $column) {
        $column->appendChild($dom->createTextNode('test'));
        $column->setAttribute('class', 'test');
    }
}

echo $dom->saveHTML();
<column>
    <row>
        <column class="test">test</column>
        <column class="test">test</column>
    </row>
</column>
© www.soinside.com 2019 - 2024. All rights reserved.