我有以下文字
hello <?tag?> world <?tag2?> xx <?/tag2?> hello <?/tag?> world
我需要将其转换为
数组( "你好", 数组( "世界", 数组( 'xx' ), '你好' ), "世界");
标签是字母数字,只要它们用匹配的标签闭合,或者<?/?>
.具有相同名称的标记可能会重复,但不会彼此内部。
我的问题是哪种方式是 CPU 效率最高?
- 将递归preg_replace与回调一起使用
- 将preg_match_all与PREG_OFFSET_CAPTURE一起使用
- 使用 preg_split 扁平化所有标签 (PREG_SPLIT_NO_EMPTY |PREG_SPLIT_DELIM_CAPTURE),进入线性阵列,然后遍历并分组标签。
如果你也能提供表达,我会很高兴。
结果不是那么简单,但希望这对其他人有所帮助。最大的复杂功能是从preg_replace的回调函数返回非字符串。
感谢所有试图帮助的人!
class Parser {
public $ret=array();
function loadTemplateFromString($str){
$this->parsed_template=$this->tags=array();
if(!$str){
return;
}
var_dump($str);
/* First expand self-closing tags <?$tag?> -> <?tag?><?/tag?> */
$str=preg_replace('/<'?'$(['w]+)'?>/','<?'1?><?/'1?>',$str);
/* Next fix short ending tag <?tag?> <?/?> -> <?tag?> <?/?> */
$x=preg_replace_callback('/.*?<'?'/'?>/',function($x){
return preg_replace('/(.*<'?([^'/]['w]+)'?>)(.*?)(<'?'/?'?>)/',
''1'3<?/'2?>',$x[0]);
},$str);
/* Finally recursively build tag structure */
$this->recursiveReplace($x);
}
function recursiveReplace($x){
if(is_array($x)){
// Called recursively
$tmp2=$this->ret;$this->ret=array();
}else{
$x=array(4=>$x);
$tmp2=null;
}
$y=preg_replace_callback('/(.*?)(<'?([^'/$]['w]+)'?>)(.*?)(<'?'/('3)?'?>)(.*?)/',
array($this,'recursiveReplace'),$x[4]);
$this->ret[]=$y;
if($tmp2===null)return;
$tmp=$this->ret;
$this->ret=$tmp2;
$this->ret[]=$x[1];
$this->ret[]=$tmp;
return '';
}
}
$p=new Parser();
$p->loadTemplateFromString('bla <?name?> name <?/name?> bla bla <?$surname?> bla '.
'<?middle?> mm <?/?> blah <?outer?> you <?inner?> are <?/?> inside <?/outer?>'.
' bobobo');
var_dump($p->ret);
这输出:
array
0 => string 'bla ' (length=4)
1 =>
array
0 => string ' name ' (length=6)
2 => string ' bla bla ' (length=9)
3 =>
array
0 => string '' (length=0)
4 => string ' bla ' (length=5)
5 =>
array
0 => string ' mm ' (length=4)
6 => string ' blah ' (length=6)
7 =>
array
0 => string ' you ' (length=5)
1 =>
array
0 => string ' are ' (length=5)
2 => string ' inside ' (length=8)
8 => string ' bobobo' (length=7)
将 <?tag
N ?>
转换为 <elem
N >
并将其解析为 XML 怎么样?
得到一个看起来像你提到的结果的原始结构后,你可以/会根据你的元素结构来验证它(即,确保项目在数字上彼此内部等)。
只需添加一个文档元素,您就可以设置以下样式表:
编辑:在这些标签与HTML混合的事实出现之后,我想我会改变我的策略。请先查看以下代码,然后再进行说明:
$data = '<b>H</b>ello <?tag?> <b>W</b>orld <?/tag?>';
$conv1 = array(
// original => entity
'<?tag' => '%START-BEGIN%',
'<?/tag' => '%START-END%'
'?>' => '%END-END%'
);
$conv2 = array(
// entity => xml
'%START-BEGIN%' => '<element',
'%START-END%' => '</element'
'%END-END%' => '>'
);
$data = str_replace(array_keys($conv1), array_values($conv1), data);
$data = htmlentities($data, ENT_QUOTES); // encode HTML characters
$data = str_replace(array_values($conv2), array_keys($conv2), data);
$xml = '<?xml version="1.0" encoding="UTF-8"?>'.$data;
// You must apply the following function to each output text
// html_entity_decode($data,ENT_QUOTES);