I have the following string:
<?foo?> <?bar?> <?baz?> hello world <?/?> <?/?> <?/?>
I need a regular expression to convert it into
<?foo?> <?bar?> <?baz?> hello world <?/baz?> <?/bar?> <?/foo?>
The following code works for non-recursive tags:
$x=preg_replace_callback('/.*?<\?\/\?>/',function($x){
return preg_replace('/(.*<\?([^\/][\w]+)\?>)(.*?)(<\?\/?\?>)/s',
'\1\3<?/\2?>',$x[0]);
},$str);
You can’t do this with regular expressions. You need to write a parser!
So create a stack (an array where you add and remove items from the end. use
array_push()array_pop()).Iterate through the tags, pushing known opening tags on the stack.
When you come to a closing tag, pop the stack and that will tell you the tag you need to close.