THTMLtag

xuzuning 2005-08-11 09:19:49
<?php
error_reporting(E_ALL);
class THTMLtag {
/**
* 类名 THTMLtag
* 功能 分析传入的HTML文本,将每个节点的信息存放入$tag_list
* 当打开debug开关时可以检查节点的嵌套情况
* html的注释标记<! >做为文本信息处理
**/
/**
* $deep 属性,用于记录当前节点的层次
**/
var $deep = 0;

/**
* $tag_list 数组,用于保存分析结果
* 结构如下
* tagname 节点名
* tagdeep 节点所处层次
* tagoffs 节点在传入文本中的偏移量(位置)
* tagend 节点被封闭时闭节点在结果集中的位置
* 其他元素 按节点已定义的属性开列
**/
var $tag_list = array();

/**
* $debug 标志,是否处于调试状态
**/
var $debug = true;

/**
* 独立的标记(不需要有闭标记的标记)
**/
var $onlytag = array('img','hr','br','meta','input','link');

/**
* 是否优化
* 使用genHTML方法生成html时使用
**/
var $optimize = false;

/**
* 方法 parse
* 功能 主控,拆分节点并指派
* 参数 $string 字符串,传入的HTML文本
**/
function parse($string) {
$ar = preg_split("/(<\/?\w+.*?>)/si",$string, -1,
PREG_SPLIT_OFFSET_CAPTURE
| PREG_SPLIT_NO_EMPTY
| PREG_SPLIT_DELIM_CAPTURE);
foreach($ar as $v) {
if(preg_match("/<(\w+)(.*)(\/?)>/s",$v[0],$r)) {
$tag = strtolower($r[1]);
$this->_tag_begin($tag,$this->_attribs($r[2]),$v[1]);
if($r[3] == '/' || in_array($tag, $this->onlytag))
$this->_tag_end($tag, $v[1]);
}elseif(preg_match("/<\/(.+)>/",$v[0],$r))
$this->_tag_end(strtolower($r[1]), $v[1]);
else
$this->_data($v[0],$v[1]);
}
if($this->debug) {
if($this->deep == 0) echo '没有发现错误<br>';
else {
foreach($this->tag_list as $v)
if(isset($v['tagend']) && $v['tagend'] == -1)
printf("位于 %d 字节处的 %s 没有配对<br>\n", $v['tagoffs'], $v['tagname']);
}
}
}

/**
* 内部方法 _tag_begin
* 功能 当节点开始时被调用,生成并保存节点的信息到结果数组
* 参数
* $tag 字符串,节点名
* $attribs 数组,节点已定义的属性。由_attribs方法产生
* $offset 数值,节点在来源中的偏移量
**/
function _tag_begin($tag, $attribs, $offset) {
$t = array('tagname' => $tag, 'tagoffs' => $offset, 'tagdeep' => $this->deep, 'tagend'=> -1, 'tagtype' => 'on');
array_push($this->tag_list, array_merge($t, $attribs));
$this->deep++;
}

/**
* 内部方法 _tag_end
* 功能 当节点关闭时被调用,调整节点层次信息
* 当debug开关打开时,进行节点嵌套检查
* 参数
* $tag 字符串,节点名
* $offset 数值,节点在来源中的偏移量
**/
function _tag_end($tag, $offset) {
$this->deep--;
if(in_array($tag, $this->onlytag)) {
$p = count($this->tag_list)-1;
$this->tag_list[$p]['tagend'] = $p;
return;
}
$t = array('tagname' => $tag, 'tagoffs' => $offset, 'tagdeep' => $this->deep, 'tagend' => 0, 'tagtype' => 'off');
$q = $p = array_push($this->tag_list, $t);
while(--$p >= 0) {
$t = $this->tag_list[$p]['tagname'];
if($tag == $t && $this->tag_list[$p]['tagend'] < 0) {
$this->tag_list[$p]['tagend'] = $q-1;
return;
}
}
}

/**
* 内部方法 _data
* 功能 当遇到不是节点的内容时被调用,保存内容到当前节点的tagtext元素
* 参数 $value 字符串,节点内容
**/
function _data($value, $offset) {
$this->count = array_push($this->tag_list, array('tagname' => '_text', 'tagoffs' => $offset, 'tagdeep' => $this->deep, 'value' => $value));
}

/**
* 内部方法 _attribs
* 功能 将传入的参数串转换为数组
* 参数 $string 字符串
* 返回 数组
**/
function _attribs($string) {
$ar = array();
$t = split(' ',preg_replace("/ *= */",'=',$string));
$st = '';
foreach($t as $k=>$v) {
$v = $st.$v;
if(preg_match("/(\w+)=([\"'])(.+)\\2/s",$v,$r)) {
$ar[strtolower($r[1])] = $r[3];
$st = '';
}elseif(preg_match("/\w+=[\"'].+/s",$v)) {
$st = $v.' ';
}elseif(preg_match("/(\w+)=([^ ]+)/s",$v,$r)) {
$ar[strtolower($r[1])] = $r[2];
}
}
return $ar;
}

/**
* 方法 genHTML
* 功能 从分析结果中生成html文档
* 返回 字符串,生成结果
**/
function genHTML() {
$retval = '';
foreach($this->tag_list as $v) {
if($v['tagname'] == '_text') {
if(preg_match("/[ \r\n]+$/",$v['value']) && $this->optimize) continue;
$retval .= $v['value'];
}else {
$retval .= ($v['tagtype']=='on' ? '<' : '</').$v['tagname'];
foreach($v as $key=>$value)
if(substr($key, 0, 3) != 'tag')
$retval .= " $key=\"".addcslashes($value, '"')."\"";
$retval .= '>';
}
}
return $retval;
}
}

if(basename(__FILE__) != basename($_SERVER['PHP_SELF'])) return;

$tpl = <<< HTML
<table
width=100><tr><td xxx=1",3'>1</td></tr></table><br>
<table><tr><td>2</td><td>
<table><tr><td>1</td></tr><table>
</td></tr></table>
HTML;

$o = new THTMLtag;
$o->parse($tpl);
print_r($o->tag_list);
echo $o->genHTML();
?>

说明:
由于几经修改,注释文字可能与代码功能不贴切,仅供参考
自行编写代码即可在结果数组中提取出所需节点及内容
...全文
396 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
gu1dai 2005-08-12
  • 打赏
  • 举报
回复
帮顶上去。

同时期待更新
flyonet 2005-08-12
  • 打赏
  • 举报
回复
看了,NB。。。。
太有用了.
flyonet 2005-08-12
  • 打赏
  • 举报
回复
老大的东西,看看!
fwqlove 2005-08-11
  • 打赏
  • 举报
回复
测试过了。
类写得不错,但是一般用在什么地方呢。
e_ 2005-08-11
  • 打赏
  • 举报
回复
呵呵 谢谢
-神仙- 2005-08-11
  • 打赏
  • 举报
回复
看到了
好东西啊
keaizhong 2005-08-11
  • 打赏
  • 举报
回复
哈哈!!多谢了。。
coolstr 2005-08-11
  • 打赏
  • 举报
回复
暂时还用不到,不过是个好东西.

值得收藏!
gu1dai 2005-08-11
  • 打赏
  • 举报
回复
冒昧修改,使结果看起来舒服点

<style>
body{font:12px verdana;}
</style>
<pre>
<?php
error_reporting(E_ALL);
class THTMLtag {
/**
* 类名 THTMLtag
* 功能 分析传入的HTML文本,将每个节点的信息存放入$tag_list
* 当打开debug开关时可以检查节点的嵌套情况
* html的注释标记<! >做为文本信息处理
**/
/**
* $deep 属性,用于记录当前节点的层次
**/
var $deep = 0;

/**
* $tag_list 数组,用于保存分析结果
* 结构如下
* tagname 节点名
* tagdeep 节点所处层次
* tagoffs 节点在传入文本中的偏移量(位置)
* tagend 节点被封闭时闭节点在结果集中的位置
* 其他元素 按节点已定义的属性开列
**/
var $tag_list = array();

/**
* $debug 标志,是否处于调试状态
**/
var $debug = true;

/**
* 独立的标记(不需要有闭标记的标记)
**/
var $onlytag = array('img','hr','br','meta','input','link');

/**
* 是否优化
* 使用genHTML方法生成html时使用
**/
var $optimize = false;

/**
* 方法 parse
* 功能 主控,拆分节点并指派
* 参数 $string 字符串,传入的HTML文本
**/
function parse($string) {
$ar = preg_split("/(<\/?\w+.*?>)/si",$string, -1,
PREG_SPLIT_OFFSET_CAPTURE
| PREG_SPLIT_NO_EMPTY
| PREG_SPLIT_DELIM_CAPTURE);
foreach($ar as $v) {
if(preg_match("/<(\w+)(.*)(\/?)>/s",$v[0],$r)) {
$tag = strtolower($r[1]);
$this->_tag_begin($tag,$this->_attribs($r[2]),$v[1]);
if($r[3] == '/' || in_array($tag, $this->onlytag))
$this->_tag_end($tag, $v[1]);
}elseif(preg_match("/<\/(.+)>/",$v[0],$r))
$this->_tag_end(strtolower($r[1]), $v[1]);
else
$this->_data($v[0],$v[1]);
}
if($this->debug) {
if($this->deep == 0) echo '没有发现错误<br>';
else {
foreach($this->tag_list as $v)
if(isset($v['tagend']) && $v['tagend'] == -1)
printf("位于 %d 字节处的 %s 没有配对<br>\n", $v['tagoffs'], $v['tagname']);
}
}
}

/**
* 内部方法 _tag_begin
* 功能 当节点开始时被调用,生成并保存节点的信息到结果数组
* 参数
* $tag 字符串,节点名
* $attribs 数组,节点已定义的属性。由_attribs方法产生
* $offset 数值,节点在来源中的偏移量
**/
function _tag_begin($tag, $attribs, $offset) {
$t = array('tagname' => $tag, 'tagoffs' => $offset, 'tagdeep' => $this->deep, 'tagend'=> -1, 'tagtype' => 'on');
array_push($this->tag_list, array_merge($t, $attribs));
$this->deep++;
}

/**
* 内部方法 _tag_end
* 功能 当节点关闭时被调用,调整节点层次信息
* 当debug开关打开时,进行节点嵌套检查
* 参数
* $tag 字符串,节点名
* $offset 数值,节点在来源中的偏移量
**/
function _tag_end($tag, $offset) {
$this->deep--;
if(in_array($tag, $this->onlytag)) {
$p = count($this->tag_list)-1;
$this->tag_list[$p]['tagend'] = $p;
return;
}
$t = array('tagname' => $tag, 'tagoffs' => $offset, 'tagdeep' => $this->deep, 'tagend' => 0, 'tagtype' => 'off');
$q = $p = array_push($this->tag_list, $t);
while(--$p >= 0) {
$t = $this->tag_list[$p]['tagname'];
if($tag == $t && $this->tag_list[$p]['tagend'] < 0) {
$this->tag_list[$p]['tagend'] = $q-1;
return;
}
}
}

/**
* 内部方法 _data
* 功能 当遇到不是节点的内容时被调用,保存内容到当前节点的tagtext元素
* 参数 $value 字符串,节点内容
**/
function _data($value, $offset) {
$this->count = array_push($this->tag_list, array('tagname' => '_text', 'tagoffs' => $offset, 'tagdeep' => $this->deep, 'value' => $value));
}

/**
* 内部方法 _attribs
* 功能 将传入的参数串转换为数组
* 参数 $string 字符串
* 返回 数组
**/
function _attribs($string) {
$ar = array();
$t = split(' ',preg_replace("/ *= */",'=',$string));
$st = '';
foreach($t as $k=>$v) {
$v = $st.$v;
if(preg_match("/(\w+)=([\"'])(.+)\\2/s",$v,$r)) {
$ar[strtolower($r[1])] = $r[3];
$st = '';
}elseif(preg_match("/\w+=[\"'].+/s",$v)) {
$st = $v.' ';
}elseif(preg_match("/(\w+)=([^ ]+)/s",$v,$r)) {
$ar[strtolower($r[1])] = $r[2];
}
}
return $ar;
}

/**
* 方法 genHTML
* 功能 从分析结果中生成html文档
* 返回 字符串,生成结果
**/
function genHTML() {
$retval = '';
foreach($this->tag_list as $v) {
if($v['tagname'] == '_text') {
if(preg_match("/[ \r\n]+$/",$v['value']) && $this->optimize) continue;
$retval .= $v['value'];
}else {
$retval .= ($v['tagtype']=='on' ? '<' : '</').$v['tagname'];
foreach($v as $key=>$value)
if(substr($key, 0, 3) != 'tag')
$retval .= " $key=\"".addcslashes($value, '"')."\"";
$retval .= '>';
}
}
return $retval;
}
}

if(basename(__FILE__) != basename($_SERVER['PHP_SELF'])) return;

$tpl = <<< HTML
<table
width=100><tr><td xxx=1",3'>1</td></tr></table><br>
<table><tr><td>2</td><td>
<table><tr><td>1</td></tr><table>
</td></tr></table>
HTML;

$o = new THTMLtag;
$o->parse($tpl);
print_r($o->tag_list);
echo $o->genHTML();
?>



gu1dai 2005-08-11
  • 打赏
  • 举报
回复
好东西
bergkamps 2005-08-11
  • 打赏
  • 举报
回复
学习、收藏
顺便感叹一下:长这么大从没见过这么强的!
wen8u8 2005-08-11
  • 打赏
  • 举报
回复
哈哈,哈哈。来看啦。
zhuangyan2004 2005-08-11
  • 打赏
  • 举报
回复
收藏,现在公司还不用PHP
huo789 2005-08-11
  • 打赏
  • 举报
回复
呵呵,多谢
-神仙- 2005-08-11
  • 打赏
  • 举报
回复
这种测试写法很像python里的
if(__name__==__main__):
jxyuhua 2005-08-11
  • 打赏
  • 举报
回复
SORRY,没看到下面有例子.
jxyuhua 2005-08-11
  • 打赏
  • 举报
回复
有个例子就更好了.先学习一下.
www0aspsun0com 2005-08-11
  • 打赏
  • 举报
回复
学习,研究,谢谢老大提供。

21,887

社区成员

发帖
与我相关
我的任务
社区描述
从PHP安装配置,PHP入门,PHP基础到PHP应用
社区管理员
  • 基础编程社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧