php截取字符串并保留完整xml标签的函数代码

复制代码 代码如下:

  <?php

  /**

  * author: goosman

  * blog: http://blog.csdn.net/lgg201

  * mail: [email protected]

  */

  $str    = '0123456789<a>012</a>0123456789';

  function substr_remain_tag($s, $o, $l) {

  $is_match   = preg_match_all(<<<heredoc

  #该正则表达式解析xml标签, 标签属性内部支持转义符"\", 支持对"\"自身和对应引号的转义

  <(\w+)             #标签开始

  (?:          #属性列表

  \s+       #前置空格

  \w+    #属性名

  \s*    #属性名后的空白(为了兼容)

  =        #属性名值之间的等号

  \s*       #属性值前的空白(为了兼容)

  (?:         #属性值(引号处理)

  "         #双引号的情况

  (?:

  \\\\\\\\   #吃掉连续两个转义符(表示转义符自身)

  \\\\"          #吃掉转义符接着一个引号(表示转义的引号)

  [^"\\\\]*   #其他字符

  )*

  "

  '       #单引号情况

  (?:

  \\\\\\\\   #吃掉连续两个转义符(表示转义符自身)

  \\\\'   #吃掉转义符接着一个引号(表示转义的引号)

  [^'\\\\]*       #其他字符

  )*

  '

  )

  )*

  >

  .*?               #标签内容

  </(?1)>     #结束标签

  ;x

  heredoc

  , $s, $matches, PREG_OFFSET_CAPTURE, $o);

  if ( $is_match ) {

  foreach ( $matches[0] as $match ) {

  $o0 = $match[1];

  #标签左边界越过截取目标右边界, 退出

  if ( $o0 >= $o + $l ) break;

  $l0 = strlen($match[0]);

  #标签右边界在截取目标右边界内, 继续

  if ( $o0 + $l0 < $o + $l ) continue;

  #以下为标签跨边界处理

  $l  = $o0 + $l0 - $o;

  break;

  }

  }

  return substr($s, $o, $l);

  }

  echo $str . chr(10);

  echo substr_remain_tag($str, 0, 20) . chr(10);