php中xml操作指南
PHP中XML操作指南
最近因为工作原因我需要学习XML, 但并不是纯技术上的XML, 而是RDF,但是我发现PHP的XML解析函数功能是一样的。我需要解析DMOZ(http://www.dmoz.org),但是出于简单性考虑我会专注于XML的基本原理,将解析DMOZ的留给你在业余时间去完成。 ;o
首先你需要确定你的PHP编译是包括'--with-xml'选项的,然后你就可以开始解析XML了。下面要抓取Slashdot的XML文件, 位置是 http://www.slashdot.org/slashdot.xml。 Slashdot的文件比较简单,易于分析。
记住操作XML文件就象操作数据库中的表。XML解析器包含结果索引,XML文档则包含伟表,一旦你明确了这种差别就不需要花费太多时间了。
PHP的XML函数允许你使用三个函数来操作XML文件中的数据:一个操作开始标记,一个操作标记间的数据, 一个操作结束标记。基本传送的标记名称,你以后可以自由的操作数据。 你先需要研究一下XML文件内容,看看包括哪些标记。 我们的Slashdot文件中包括STORY, TITLE, URL, TIME, AUTHOR, DEPARTMENT, TOPIC, COMMENTS, SECTION和IMAGE标记。有些标记包含属性值,例如HREF是标记A的一个属性, PHP有很优秀的方法来自动处理属性值。 下面我们在脚本中定义这些标记。
———— PHP代码 ————
<?php
$open_tags = array(
'STORY' => '<STORY>',
'TITLE' => '<TITLE>',
'URL' => '<URL>');
$close_tags = array(
'STORY' => '</STORY>',
'TITLE' => '</TITLE>',
'URL' => '</URL>');
?>
————————————
我只想分析上面的这些数据,因为我只需要一些很酷的Slash框子。 下面就是定义函数来提取数据:
———— PHP代码 ————
<?php
// 处理开始标记的属性指
// $attrs是一个多维数组,键值为属性名, 值就是该属性的值
function startElement($parser, $name, $attrs=''){
global $open_tags, $temp, $current_tag;
$current_tag = $name;
if ($format = $open_tags[$name]){
switch($name){
case 'STORY':
echo '新的故事: ';
break;
default:
break;
}
}
}
// $current_tag告诉我们正在处理的标记,我们随后会在characterData函数中使用
//
// 当遇到</STORY>标记时我们知道要flush所有的临时变量准备操作下一个标记
[php]
function endElement($parser, $name, $attrs=''){
global $close_tags, $temp, $current_tag;
if ($format = $close_tags[$name]){
switch($name){
case 'STORY':
return_page($temp);
$temp = '';
break;
default:
break;
}
}
}
// 传送给此函数的是元素间的数据
// 例如,对<TITLE>Title Here</TITLE>,$data就等于'Title Here'
function characterData($parser, $data){
global $current_tag, $temp, $catID;
switch($current_tag){
case 'TITLE':
$temp['title'] = $data;
$current_tag = '';
break;
case 'URL':
$temp['url'] = $data;
$current_tag = '';
break;
default:
break;
}
}
?>
————————————
到现在为止你可以看到用PHP分析XML文件不是很糟糕的事,下面就是有趣的内容了 -- 分析文件。 看下面的代码, 还是很简单的:
———— PHP代码 ————
<?php
function return_page(){
global $temp;
echo 'o <A HREF="'.$temp['url'].'">'.$temp['title'].'</A><BR>';
}
// 分析的内容
$xml_file = 'slashdot.xml';
// 定义字符集,默认是UTF-8
$type = 'UTF-8';
// 建立解析器
$xml_parser = xml_parser_create($type);
// 设置解析选项
xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, true);
xml_parser_set_option($xml_parser, XML_OPTION_TARGET_ENCODING, 'UTF-8');
// 告诉PHP发现元素时要调用什么函数
// 这些函数同时也处理元素的属性
xml_set_element_handler($xml_parser, 'startElement','endElement');
// 告诉PHP对字符数据调用什么函数
xml_set_character_data_handler($xml_parser, 'characterData');
if (!($fp = fopen($xml_file, 'r'))) {
die("无法打开 $xml_file 文件进行解析!n");
}
// 通过循环来解析整个文件
while ($data = fread($fp, 4096)) {
if (!($data = utf8_encode($data))) {
echo 'ERROR'."n";
}
if (!xml_parse($xml_parser, $data, feof($fp))) {
die(sprintf( "XML error: %s at line %dnn",
xml_error_string(xml_get_error_code($xml_parser)),
xml_get_current_line_number($xml_parser)));
}
}
xml_parser_free($xml_parser);
?>
————————————
所发生的情况是:PHP开始解析,直到遇到<ELEMENT ATTRIBUTE='bold'>,然后传送ELEMENT和其属性给startElement函数。 因为Slashdot的文件并不包含属性,我们不需要关心这一步,但是如果有属性, 就是这样的情况。然后传送起止元素间的数据给characterData函数,最后传送结束元素及其属性给endElement函数。endElement函数调用return_page()函数, 但是是在发现已经到达数据的结尾时。直到此刻$temp变量才包含startElement和characterData函数收集的数据。
下面所要做的就只是在你的cron操作里面加入wget!