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);

發佈了123 篇原創文章 · 獲贊 1149 · 訪問量 130萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章