首页 > 语言 > PHP > 正文

通用XML文件数据解析的PHP类

2024-09-04 11:50:11
字体:
来源:转载
供稿:网友
网上那种可在php4,5默认配置环境下运行的通用解析XML的PHP类, 好像不多

至少我没找到, 所以就写了这个, 放上来大家讨论一下!

希望能得到各位宝贵的意见, 并能完善此类!

我作了几个测试的路径! 大家可先看看效果!

源文件下载在下面!.... 为了大家看得方便,注释有点嗦了。

<?php

/*****************************************************************************
* xmlRead 类
* ---------------------------------------------------------------
* 描述:XML文件数据读取类(SAX 解析)
* 运行环境: PHP4,PHP5 最好有 iconv() 函数支持
* 用途: 用于读取xml文件数据到一数组里,目前还不能对一些特殊的标记进行处理
* 特点: 可为同级兄弟结点指定索引(数组下标)
* -----------------------------------------------------------------
* 作者: Mayer
* 邮箱: luck@21php.com
* QQ号: 65712936
* 日期: 2005-01-16 16:29:00
* ---------------------------------------------------------------------
* 所属团队: 中文PHP
* 版权说明:本文件仅供测试,希望碰到任何问题或者有建议,能给原作者发 Email 反馈.
* 在保留原作者和本说明的前提下,你可以任意使用,但作者没有义务做技术支持。
* 你可任意修改本文件,但必须保留头部的说明,同时希望能通知原作者你的改动。
* 测试地址: http://luck1314.com/mywork/xml_class.php?t=1
* http://luck1314.com/mywork/xml_class.php?t=2
* http://luck1314.com/mywork/xml_class.php?t=3
* http://luck1314.com/mywork/xml_class.php?t=4
* http://luck1314.com/mywork/xml_class.php?t=5
* 由于测试服务器不支持iconv函数所以第一个带中文标签的测试显示中文为乱码,
* 而查看网页源码看是正常的,如大家知道解决的方法请告诉我。谢谢!
* 测试时, 大家看看各xml文件结构
* 讨论原帖: http://club.21php.com/showthread.php?p=34516#post34516
*****************************************************************************/
class xmlRead
{
//解析器
var $var_parser;

//xml文件编码语言
var $var_lang = 'GB2312';

//*****************************************************
// $var_node[深度][节点名] node_name
// $var_node[深度][目标类型] target_type
// $var_node[深度][目标名称] target_name
// 目标: 属性/子节点; 0/1
// 深度: 数字 - by Mayer
//*****************************************************
var $var_node = array();
var $var_index = array();

var $var_stack = array(); //标记栈
var $var_stack_attrs = array(); //参数栈

//节点深度
var $var_depth = 0;

// $var_data[深度]; $var_data[0] 用来存 xml文件所有记录
var $var_data = array(); //数据

function xmlRead($file,$node='',$lang)
{
if(is_array($node))
{
$this->var_node = $node;
}
if($file)
{

if('UTF-8' == strtoupper($lang))
{
$this->var_parser = xml_parser_create('UTF-8');
}
else
{
$this->var_parser = xml_parser_create();
if('GBK' == strtoupper($lang))
{
$this->var_lang = $lang;
}
}
xml_set_object($this->var_parser,&$this);
xml_parser_set_option($this->var_parser, XML_OPTION_CASE_FOLDING, 0);
xml_set_element_handler($this->var_parser, "startElement", "endElement");
xml_set_character_data_handler($this->var_parser, "characterData");

$this->xmlRead_parser_file($file);
}
}

/******************************************************
* 获取xml数据记录 -by Mayer 2005-1-17
******************************************************/
function xmlRead_get_ret()
{
return $this->var_data[0];
}

function xmlRead_parser_file($file)
{
if (!($fp = fopen($file, "r")))
{
die("could not open XML input");
}
$data = fread($fp, 4096);
if('GBK' == $this->var_lang)
{
//$data = str_replace(array('utf-8','gb2312','UTF-8','GB2312'),'GBK',$data);
$data = preg_replace("/encoding=(.+)?>/",'encoding="GBK" ?>',$data);
}

elseif('UTF-8' == $this->var_lang)
{

}
do
{
if(!xml_parse($this->var_parser, $data, feof($fp)))
{
die(sprintf("XML error: %s at line %d",
xml_error_string(xml_get_error_code($this->var_parser)),
xml_get_current_line_number($this->var_parser)
)
);
}
}while($data = fread($fp, 4096));
xml_parser_free($this->var_parser);
}

function startElement($parser, $name, $attrs)
{
if(function_exists('iconv'))
{
$name = iconv('UTF-8', $this->var_lang, $name);
}

//节点开始, 节点名入栈
array_push($this->var_stack,$name);
array_push($this->var_stack_attrs,$attrs);
//设置节点深度
$this->var_depth = count($this->var_stack) - 1;


if($this->var_depth > 0)
{

//判断现在是否只有一个同级同名兄弟结点
// 当前深度标识的数据是否为一数组 && 是否存在同级同名索引为 $this->var_index[$this->var_depth][$name]] 的记录存在
// 或同级同名兄弟结点数据为字符串
if(is_array($this->var_data[$this->var_depth][$name]) && !isset($this->var_data[$this->var_depth][$name][$this->var_index[$this->var_depth][$name]]) || is_string($this->var_data[$this->var_depth][$name]))
{
//判断是否有索引设置
if($this->var_node[$this->var_depth]['node_name'] == $name)
{
//如果索引值不存在...
if(!$this->var_index[$this->var_depth][$name])
{
if(intval($this->var_node[$this->var_depth]['target_type']) == 1)
{
$index = $this->var_data[$this->var_depth][$name][$this->var_node[$this->var_depth]['target_name']];
if(is_array($index))
{
$this->var_index[$this->var_depth][$name] = 0;
}
}
else
{
$this->var_index[$this->var_depth][$name] = $attrs[$this->var_node[$this->var_depth]['target_name']];
}
}
}
else
{
$this->var_index[$this->var_depth][$name] = 0;
}
$this->var_data[$this->var_depth][$name] = array($this->var_index[$this->var_depth][$name]=>$this->var_data[$this->var_depth][$name]);
}

}
//检查节点类型,
}

function endElement($parser, $name)
{
if(function_exists('iconv'))
{
$name = iconv('UTF-8', $this->var_lang, $name);
}
//判断下级结点数据是否存在
if(is_array($this->var_data[$this->var_depth+1]) && count($this->var_data[$this->var_depth+1]))
{
//判断同级结点是否存在 如在标签结束时同级结点存在的话那在这级同名结点为多数 同级同名首结点在startElement里判断并重命名索引
//同级同名索引存在否 && 同级同名索引数据存在否
if(isset($this->var_index[$this->var_depth][$name]) && isset($this->var_data[$this->var_depth][$name][$this->var_index[$this->var_depth][$name]]))
{
//判断是否要设置结点索引
if($this->var_node[$this->var_depth]['node_name'] == $name)
{
if($this->var_node[$this->var_depth]['target_type'] == 0)
{
$attrs = end($this->var_stack_attrs);
if(count($attrs))
{
$index = $attrs[$this->var_node[$this->var_depth]['target_name']];
}
}
else
{
$index = $this->var_data[$this->var_depth+1][$this->var_node[$this->var_depth]['target_name']];
}
$this->var_data[$this->var_depth][$name][$index] = $this->var_data[$this->var_depth+1];
}
else
{
$this->var_data[$this->var_depth][$name][] = $this->var_data[$this->var_depth+1];
}
}
else
{
$this->var_data[$this->var_depth][$name] = $this->var_data[$this->var_depth+1];
//在还没有同级结点的时候,判断是否要设置索引
if($this->var_node[$this->var_depth]['node_name'] == $name)
{
if(intval($this->var_node[$this->var_depth]['target_type']) == 1)
{
$index = $this->var_data[$this->var_depth][$name][$this->var_node[$this->var_depth]['target_name']];
if(is_array($index))
{
$index = 0;
}
}
else
{
$attrs = end($this->var_stack_attrs);
$index = $attrs[$this->var_node[$this->var_depth]['target_name']];
}

//设置索引值
$this->var_index[$this->var_depth][$name] = $index;
}
else
{
//索引默认为 0
$this->var_index[$this->var_depth][$name] = 0;
}
}
}
unset($this->var_data[$this->var_depth+1]);
unset($this->var_index[$this->var_depth+1]);
//print_r($this->var_data[$this->var_depth][$name]);
//echo " : $name<br>";
//节点结束, 节点名出栈
array_pop($this->var_stack);
array_pop($this->var_stack_attrs);
$this->var_depth = count($this->var_stack) - 1;
}

function characterData($parser,$data)
{
if(trim($data) !== '')
{
$name = end($this->var_stack);
if(function_exists('iconv'))
{
$data = iconv('UTF-8', $this->var_lang, $data);
}
//echo $data."<br>";
//判断是否已经有同级并同名的记录存在
if(is_array($this->var_data[$this->var_depth][$name]))
{
//判断是否要设置结点索引
if($this->var_node[$this->var_depth]['node_name'] == $name && $this->var_node[$this->var_depth]['target_type'] == 0)
{
$attrs = end($this->var_stack_attrs);
if(count($attrs))
{
$index = $attrs[$this->var_node[$this->var_depth]['target_name']];
}
$this->var_data[$this->var_depth][$name][$index] = $data;
}
else
{
$this->var_data[$this->var_depth][$name][] = $data;
}
}
else
{
$this->var_data[$this->var_depth][$name] = $data;
//在还没有同级结点的时候,判断是否要设置索引
if($this->var_node[$this->var_depth]['node_name'] == $name && $this->var_node[$this->var_depth]['target_type'] == 0)
{
$attrs = end($this->var_stack_attrs);
$index = $attrs[$this->var_node[$this->var_depth]['target_name']];

//设置索引值
$this->var_index[$this->var_depth][$name] = $index;
}
else
{
//索引默认为 0
$this->var_index[$this->var_depth][$name] = 0;
}
}
}
}
}


//------------------------ XMLREAD 类的用法如下 ------------------------------------------------------
$node = array();
switch($_REQUEST['t'])
{
case 1 : {//----解析编码为UTF-8格式的XML文件,标签为中文---------------------------------
$file = 'test_mod.xml';
$lang = 'UTF-8';
break;
}
case 2 : {//----解析编码为GB2312格式的XML文件------------------------------------------
$file = 'ex34.xml';
$lang = 'GB2312';
break;
}
case 3 : {//----解析含有GBK繁体字数据的XML文件------------------------------------------
$file = 'week_game.xml';
$lang = 'GBK';
break;
}
case 4 : {//----解析含有GBK繁体字数据的XML文件,并指定第2级名为m的结点的索引(数组下标)为其子结点i的值---
$file = 'week_game.xml';
$node[2] = array(
'node_name'=>'m',
'target_type'=>1,
'target_name'=>'i'
);
$lang = 'GBK';
break;
}
case 5 : {//解析含有GBK繁体字数据的XML文件,并指定索引------------------------------------
$file = 'Europe_Full.xml';
$node[1] = array(
'node_name'=>'d',
'target_type'=>0,
'target_name'=>'d'
);
$node[2] = array(
'node_name'=>'m',
'target_type'=>1,
'target_name'=>'i'
);
$lang = 'GBK';
break;
}
default :{//---------------------------------------
$file = 'test_mod.xml';
$lang = 'UTF-8';
break;
}
}

$xml = new xmlRead($file,$node,$lang);
echo "<pre>";
print_r($xml->xmlRead_get_ret());
echo "</pre>";
?>
上一篇:在PHP使用json_encode

下一篇:php面试题目

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表