使用php的tidy解析html

以前解析html都是使用正则表达式,但是用起来比较麻烦。现在开始使用php的tidy库。

示例如下: 摘自:http://us3.php.net/tidy.root

<?php
 
$html = <<< HTML
 
paragraph
 
HTML;
 
$tidy = tidy_parse_string($html);
dump_nodes($tidy->root(), 1);
 
function dump_nodes($node, $indent) {
 
    if($node->hasChildren()) {
        foreach($node->child as $child) {
            echo str_repeat('.', $indent*2) . ($child->name ? $child->name : '"'.$child->value.'"'). "\n";
 
            dump_nodes($child, $indent+1);
        }
    }
}
?>

要注意的一点是,对于GBK编码的HTML需要先转换编码为UTF8的,然后使用

$tidy = new tidy;
$tidy ->parseString($html, array(), 'utf8');

来解析。

====后续分割线===

最近又使用一种新的方法来解析html,当然还是用php。

使用一个叫做PHP Simple HTML DOM Parser的类。感谢某同学的帮助。

英文链接地址:http://simplehtmldom.sourceforge.net/

中文链接地址:http://phpdom.comsing.com/

这个类使用起来非常方便,单就解析html这一点来说,比tidy好用。而且文档齐全,简单易懂。

示例如下:

                $html = new simple_html_dom();
		$html->load($content);
 
		$result = array();
 
		foreach($html->find('a') as $a){
			$img = $a->find('img', 0);
			if(isset($a->href) && isset($img->src)){
				$result[] =  array(
							'href' => $a->href,
							'src'  => $img->src,
				);
 
			}
		}
Posted in PHP. Tags: , . 没有评论 »

phpDocumentor学习笔记

前言:
使用phpDocumentor的好处:
你喜歡寫文件嗎?我不喜歡。尤其是在趕工的時候,哪來的美國時間寫文件;就算有時間也是希望趕快把事情做完閃人,怎樣都輪不到寫文件的時候。

文件需要嗎?雖然不喜歡寫文件,但文件真的是必要的。對自己而言,正當在趕案子兵荒馬亂的時候,突然要某個以前寫過的函式結果不知道放哪去了,這時心情會很糟很糟的去把以前的碼挖出來一份一份看,才能找出所要的函式,這樣更浪費時間。對於他人而言,要是每個人寫出來的東西都可以再讓其它人了解,並且進一步使用其它人早已寫好的元件,可以讓我們再省下時間來多喝幾杯咖啡。

那要怎麼樣讓編寫文件輕鬆又自在? phpDocumentor 就是一個現成好用的工具,只要在寫程式時順手寫上一點點的註解,困難一點的可以再加上一點點的範例。寫完後交給 phpDocumentor 編譯,一下子圖文並茂的程式文件自動就產生了。而且它還不只可以產生 HTML 檔,還可以產生出 PDF, CHM 等文件。就算產生 HTML 檔,還有許多的風格可以選擇。這樣好用的工具放著不用,實在太可惜了。

這份資料裡,只會出現馬上能用的資料,除了這個簡介外,不會廢話太多,所以文件中的文句也冰冷了些。會這樣做的目的是希望文件的每一個部份都能讓讀者快速吸收,任何一個例子複製下來後馬上能用。文件中的每個樣版我都是精心設計過,起碼我以後要用的時候不必再想說要寫一個類別正常需要哪些 Tag ,只要把樣版複製下來以後就直接可以用了。

由於此文件中資料只有使用上最需要的部份(也是一定能用的部份),因此若在使用上想要了解更多,可以到 phpDocumentor 的官方網站 (http://www.phpdoc.org/)上找到所需資料。
——————摘自 《phpDocumentor筆記 0 立即體驗》
http://pkwbim-programming-note.blogspot.com/2008/01/phpdocumentor-0.html#0.4

其实这篇文章已经写的比较简要,但是为了防止哪天这个网站被盾了,我还是抄到自己的blog比较安全。
简而言之,phpDocumentor就适合我这样写过代码就忘了的人,规范的书写注释还能生成文档,多省事。

1.安装
1.1如果没有安装过pear,可以先运行PHP目录下的go-pear.bat安装。
1.2安装过pear之后,使用下面的命令安装phpDocumentor:
\php5\PEAR\pear install -o PhpDocumentor

2.字符编码的问题
看到很多人都说需要改字符编码,但是我下载的phpDocumentor v1.4.2 没有遇到这个问题,也没有
查找到”iso-8859-1″这个字符串。

3.生成文件
步驟

3.1 将範例碼存成 example.php 置於 \project\php_project\下。
3.2 在命令列下用以下指令

phpdoc –parseprivate -o HTML:frames:earthli -f \project\php_project\example.php -t \project\php_project\docs

phpdoc –parseprivate -o HTML:Smarty:PHP -d \project\php_project\ -t \project\php_project\docs

3.3 解說
* –parseprivate: 是將私有 (private) 成員函式或私有變數等等也都加入程式文件裡。沒有這參數的話,產生出的文件裡只會有公開的 (public) 和受保護的 (protected) 的成員函式和變數。
* -f : 是指針對某個檔案產生註解文件。
* -d : 針對某個目錄(含其子目錄)產生註解文件。
* -t : 指定要輸出的目錄
* -o : 指定輸出格式,上例的格式有兩種
o HTML:frames:earthli : 是輸出有一種帶有框架 (frame) 的說明文件,所產生出來的文件非常漂亮。Zend Framework 的 API 文件就是採用這種風格。
o HTML:Smarty:PHP : 產生的文件看起來就像是 PHP 網站上或是 phpDocumentor 官網上的的一樣。

待程式結束後,瀏覽剛剛指定產生文件的目錄下,會有一個 index.html 檔,以瀏覽器打開它就可以看到 phpDocumentor 產生出來的程式文件。倘若在產生文件的過程中,有任何的錯誤,這些錯誤會出現在 error.html檔裡。

4.范例

&lt;?php
/**
* phpDocumentor 使用示範
* 這個檔案是一個簡單的示範
* 內容涵蓋了許多常用的註解方式。
* 有任何的問題請和作者連絡
* @package phpDocumentorExample
* @author 多采多姿 &lt;pkwbim.programming@gmail.com&gt;
* @version 0.1b
*/
 
/**
* 這是 lib.inc.php 的標題
* 這是 lib.inc.php 的描述
*/
include_once('lib.inc.php');
 
/**
* 圓周率
* 圓周和直徑的比值
*/
define('pi', 3.14159);
 
/**
*  這是 funtion1 的註解區塊標題
*  這是 funtion1 的描述
*  @global int 這是函式內第一個全域變數的註解,就是 $global1 的註解
*  @global string 這是函式內第二個全域變數的註解,就是 $global2 的註解
*  @param bool $arg1 這是函式參數 $arg1 的註解
*  @param int|string $arg2 這裡是函式參數 $arg2 的註解
*  @return mixed 傳回值的註解
*/
function function1($arg1, $arg2) {
global $global1, $global2;
return array($arg1, $arg2);
}
 
/**
* 這是MyClass的標題
*
* 建立簡寫型的清單
* 這裡建立一份無序清單
* - 項目一
* - 項目二,
*   每個項目可以是多行,
*   就像這個項目,
*   這行還在項目二中
* - 項目三
* 清單結束,因為沒縮排
* 這裡建立一份有序清單
* 1 有序的項目一,數字後一定要加一個空白。
* 2 有序的項目二
* 有序清單的另一種寫法
* 1. ordered item 1
* 2. ordered item 2
* 清單在此結束
*
* @package phpDocumentorExample
* @author 多采多姿
* @since 1.0rc1
* @version 0.2b
*
*/
class MyClass {
/**
* 這裡是成員變數的註解
*
* @var string 成員變數的註解
* @access private
*/
private $_variable = "Hello";
 
/**
* 這是一個公開的成員函式
*
* @param bool $var1 參數1
* @param string|array $var2 參數1
* @return void
* @access public
*/
public function set_vars($var1, $var2) {
}
}
?&gt;

要注意所有的注释都是有两个星号的C-style注释,如下所示

/**
*
*/

语法参考文档: http://manual.phpdoc.org/HTMLSmartyConverter/HandS/phpDocumentor/tutorial_phpDocumentor.quickstart.pkg.html#coding

Posted in PHP. Tags: , . 没有评论 »

字符串编码转换小结2

 今天早上,网页忽然正常显示了,原来是修改了注册表的原因。
 在数据库迁移后(sql server :gbk2312 到 Oracle : UTF8),可能出现页面字符乱码的原因:

1.oracle字符集设置不正确。

数据库服务器字符集select * from nls_database_parameters,其来源于props$,是表示数据库的字符集。客户端字符集环境select * from nls_instance_parameters,其来源于v$parameter,表示客户端的字符集的设置。可能是参数文件,环境变量或者是注册表会话字符集环境select * from nls_session_parameters,其来源于v$nls_parameters,表示会话自己的设置,可能是会话的环境变量或者是alter session完成,如果会话没有特殊的设置,将与nls_instance_parameters一致。

客户端的字符集要求与服务器一致,才能正确显示数据库的非Ascii字符。如果多个设置存在的时候,alter session>环境变量>注册表>参数文件字符集要求一致,但是语言设置却可以不同,语言设置建议用英文。如字符集是zhs16gbk,则nls_lang可以是American_America.zhs16gbk;如果字符集是utf8,则要改成SIMPLIFIED CHINESE_CHINA.AL32UTF8。(即hkey_local_machine => software => oracle =>NLS_LANG改为SIMPLIFIED CHINESE_CHINA.AL32UTF8)

2.迁移过程中字符编码转换不正确,如何转换编码可参照总结1。
在php中,可以使用mb_string 的mb_detect_encoding来检测字符串是什么编码。

3.脚本代码要另存为utf8格式。

4.页面的header 要设置为utf8。

 

Posted in Oracle, other. Tags: , . 没有评论 »

Zend Framework中对oracle数据库操作总结

说明: 摘自ZF手册中文版
1.执行查询并返回结果
跳过废话
1.1 使用 Zend_Db_Adapter
 一旦你得到了一个Zend_Db_Adapter 实例, 你可以直接
执行sql语句进行查询. Zend_Db_Adapter 传送这些sql语
句到底层的PDO对象,由PDO对象组合并执行他们,在有查询结果的情况
下,返回一个PDOStatement对象以便对结果进行处理。

<?php

// 创建一个$db对象,然后查询数据库// 使用完整的sql语句直接进行查询.$sql = $db->quoteInto(    'SELECT * FROM example WHERE date > ?',    '2006-01-01');$result = $db->query($sql);

// 使用PDOStatement对象$result将所有结果数据放到一个数组中$rows = $result->fetchAll();

?>

或者使用fetch开头系列方法获得结果集:

对于每一种 fetch系列 的方法来说,你需
要传送一个select的sql语句;假如你在操作语句中使用指定的占位符,你也可以
传送一个绑定数据的数组对你的操作语句进行处理和替换。 Fetch系列
的方法包括:

  • fetchAll()

  • fetchAssoc()

  • fetchCol()

  • fetchOne()

  • fetchPairs()

  • fetchRow()

<?php

// 创建一个 $db对象, 然后...

// 取回结果集中所有字段的值,作为连续数组返回$result = $db->fetchAll(    "SELECT * FROM round_table WHERE noble_title = :title",    array('title' => 'Sir'));

// 取回结果集中所有字段的值,作为关联数组返回// 第一个字段作为码$result = $db->fetchAssoc(    "SELECT * FROM round_table WHERE noble_title = :title",    array('title' => 'Sir'));

// 取回所有结果行的第一个字段名$result = $db->fetchCol(    "SELECT first_name FROM round_table WHERE noble_title = :title",    array('title' => 'Sir'));

// 只取回第一个字段值$result = $db->fetchOne(    "SELECT COUNT(*) FROM round_table WHERE noble_title = :title",    array('title' => 'Sir'));

// 取回一个相关数组,第一个字段值为码// 第二个字段为值$result = $db->fetchPairs(    "SELECT first_name, favorite_color FROM round_table WHERE noble_title = :title",    array('title' => 'Sir'));

// 只取回结果集的第一行$result = $db->fetchRow(    "SELECT * FROM round_table WHERE first_name = :name",    array('name' => 'Lancelot'));

?>

1.2 使用Zend_Db_Select方法

使用Zend_Db_Select方法是一种不受数据库约束构建select的sql语句的工具
(ares注:用户可以使用该方法生成查询的sql语句,而不需要考虑各种数据
库sql语句的差别)。虽然该方法明显还不完善,但是的确为我们提供一种方
法,帮助我们在不同的后台数据库进行相同的查询工作。除此之外,它还可
以避免sql语句攻击。

创建一个zend_db_select实例最简单的方法就是使用zend_db_adapter::select()方法

<? php

//在model中取得连接,并进行相应数据库操作

$this->db = Zend_Registry::get('db');        

$select = $this->db->select(); $select->from('link_info', 'link_info.*')                ->join('link_tag_collect', 'link_info.linkid=link_tag_collect.linkid')                ->where('user_friend.userid=?',$userid)

               ->distinct(link_info.linkid)               ->order('link_tag_collect.addtime DESC')                -2007-12-18>limit(10,0); $sql = $select->__toString();          $result = $this->db->fetchALL($sql); 

?>

1.3 使用 Zend_Db_Table
Zend_Db_Table 是Zend Framework的表模块.它通过zend_db_adapter连接到数据库,为数据库模式检查表对象,
并对该表进行操作和查询.

<?phpclass RoundTable extends Zend_Db_Table {}

$table = new RoundTable();$db = $table->getAdapter();

// SELECT * FROM round_table//     WHERE noble_title = "Sir"//     ORDER BY first_name//     LIMIT 10 OFFSET 20

$where = $db->quoteInto('noble_title = ?', 'Sir');$order = 'first_name';$count = 10;$offset = 20;

$rowset = $table->fetchAll($where, $order, $count, $offset);?>

以上都为废话,从ZF手册中皆能得到。

  • 从model中获得数据库连接,然后使用ZEND_DB_SELECT。

在tag.php中

<?php public function getTopTag(){                $select = $this->db->select();        $select->from($this->_name, '*')               ->order('TAGTOTAL DESC')               ->limit(10,0);             

        $sql = $select->__toString();        $result = $this->db->fetchALL($sql);        return $result;    }?>

在TagController.php中

<?phpclass TagController extends Zend_Controller_Action	private $tag;	function init() {		parent::init();		Zend_Loader::loadClass('Tag');				$this->tag = new Tag();			}	function topAction(){		$thi->tag->getTopTag();		...	}?>

  • 使用ZEND_DB_TABLE

在Tag.php中

<?phpclass Tag extends Zend_Db_Table{    protected $_name = "TAG_INFO";    protected $_primary = 'TAGID';}?>在TagController.php中<?phpclass TagController extends Zend_Controller_Action	private $tag;	function init() {		parent::init();		Zend_Loader::loadClass('Tag');				$this->tag = new Tag();			}	function topAction(){		$order = 'TAGTOTAL';			$count = 10;		$offset = 0; 		$thi->tag->fetchAll( $order, $count, $offset);		...	}?>

最好还是选用方法一,能够将对数据的操作都封装在model中。
2.插入数据
无论是DB还是Table类,都使用insert()方法。
对于Oracle来说,如果要使用sequence作为自增的主键的话,需要使用trigger。
比如,有tag表,主键为tagid,其对应的sequence为tag_seq,要插入数据时,需要先新建trigger:

create or replace trigger tag_tri
before insert on tag
for each row
declare
nextid number;
begin
IF :new.tagid IS NULL or :new.tagid=0 THEN
select tag_seq.nextval
into nextid
from sys.dual;
:new.tagid:=nextid;
end if;
end tag_tri;

其余部分和插入其它数据库相同

<?php$table_name='TAG';$row = array (		'TAGNAME'   => $tagname,		'TAGTOTAL'  => '1'	);$this->db->insert($table_name,$row);?>

3.更新数据
3.1直接执行update语句,参见文档。
3.2如果update语句中,有包含数据库的特殊关键字时,需要先将数据选出,然后再更新

<?php	$where = $this->db->quoteInto('tagname = ?',$tagname);	$rowset = $this->tag->fetchAll($where);	$count=$rowset->count();	$tag = $rowset->current();						if($count!=0){		$tagid=$tag->TAGID;		//tagtotal+1

		$tag->TAGTOTAL ++;  //应判断一下当前用户是否		$tag->save();		}?>

4.删除数据

<?php	//删除已有的collect表中记录	// where条件语句	$where = $this->db->quoteInto('USERID = ?', $userid)		.$this->db->quoteInto('AND LINKID = ?', $linkid);

	// 删除数据并得到影响的行数	$rows_affected =  $this->collect->delete($where);?>

总结完毕:
tips:
注意表名、字段名等的大小写!

Posted in PHP. Tags: , , . 没有评论 »