PHP - 内部HTML递归替换

时间:2014-02-12 13:28:38

标签: php regex innerhtml

我需要在HTML的一部分上执行递归str_replace(递归我的意思是第一个内部节点),所以我写道:

$str = //get HTML;
$pttOpen = '(\w+) *([^<]{1,100}?)';
$pttClose = '\w+';
$pttHtml = '(?:(?!(?:<x-)).+)';

while (preg_match("%<x-(?:$pttOpen)>($pttHtml)*</x-($pttClose)>%m", $str, $match)) {
    list($outerHtml, $open, $attributes, $innerHtml, $close) = $match;
    $newHtml = //some work....
    str_replace($outerHtml, $newHtml, $str);
}

这个想法是首先替换非嵌套的x-tag。 但只有当innerHtml位于开始标记的同一行时才会起作用(所以我想我误解了/ m修饰符的作用)。我不想使用DOM库,因为我只需要简单的字符串替换。有什么帮助吗?

3 个答案:

答案 0 :(得分:1)

试试这个正则表达式:

%<x-(?P<open>\w+)\s*(?P<attributes>[^>]*)>(?P<innerHtml>.*)</x-(?P=open)>%s

演示

http://regex101.com/r/nA2zO5

示例代码

$str = // get HTML
$pattern = '%<x-(?P<open>\w+)\s*(?P<attributes>[^>]*)>(?P<innerHtml>.*)</x-(?P=open)>%s';

while (preg_match($pattern, $str, $matches)) {
    $newHtml =  sprintf('<ns:%1$s>%2$s</ns:%1$s>', $matches['open'], $matches['innerHtml']);
    $str = str_replace($matches[0], $newHtml, $str);
}

echo htmlspecialchars($str);

输出

最初,$str包含以下文字:

<x-foo>
    sdfgsdfgsd
       <x-bar>
           sdfgsdfg
       </x-bar>
       <x-baz attr1='5'>
           sdfgsdfg
       </x-baz>
    sdfgsdfgs
</x-foo>

最终:

<ns:foo>
   sdfgsdfgsd
   <ns:bar>
       sdfgsdfg
   </ns:bar>
   <ns:baz>
       sdfgsdfg
   </ns:baz>
   sdfgsdfgs
</ns:foo>

由于我不知道在$newHtml上做了哪些工作,我通过将x-替换为ns:并删除任何属性来模仿这项工作。

答案 1 :(得分:1)

感谢@Alex我想出了这个:

%<x-(?P<open>\w+)\s*(?P<attributes>[^>]*?)>(?P<innerHtml>((?!<x-).)*)</x-(?P=open)>%is

如果没有内部HTML模式中的((?!&lt; x - )。)*),它将不适用于嵌套标签(它将首先匹配外部标签,这不是什么我想了)。这样最里面的那些首先匹配。希望这会有所帮助。

答案 2 :(得分:1)

我不确切地知道你要做什么样的改变,但这是我要继续的方式:

$pattern = <<<'EOD'
~
    <x-(?<tagName>\w++) (?<attributes>[^>]*+) >
    (?<content>(?>[^<]++|<(?!/?x-))*) #by far more efficient than (?:(?!</?x-).)*
    </x-\g<tagName>>
~x
EOD;

function callback($m) { // exemple function
    return '<n-' . $m['tagName'] . $m['attributes'] . '>' . $m['content']
         . '</n-' . $m['tagName'] . '>';       
};

do {
    $code = preg_replace_callback($pattern, 'callback', $code, -1, $count);
} while ($count);


echo htmlspecialchars(print_r($code, true));