经测试代码如下:
/**
* xml分析类
*
* @param
* @arrange (编程之家) jb51.cc
**/
************************************************************************
Example:
************************************************************************
$xml = new XML('artikel.xml');
$xml->print_nodes();
?>
***********************************************************************
Script
***********************************************************************
<?php
#此脚本根据某些规则格式化xml文件。 这些规则
#在xml_set_character_data_handler的函数中处理
# define。 我们必须记住,我们在哪个元素,此外,
#当前元素具有的祖先元素。
class Node {
var $name;
var $attributes;
var $ancestors = /
var $data;
var $type;
function Node($tree) {
$this->name = array_pop($tree);
$this->ancestors .= implode(/,$tree);
}
function add_data($value) {
$this->data .= ' '.$value;
}
function get_type() {
if (strlen($this->data) > 0) {
return with CDATA
} else {
return without CDATA
}
}
function level() {
if ($this->ancestors == /) return 0;
if (preg_match_all(/(\/{1})/,$this->ancestors,$result,PREG_PATTERN_ORDER)) {
return (count($result[0]));
} else {
return 0;
}
}
function has_attributes() {
return (is_array($this->attributes));
}
function print_name() {
return $this->name;
}
function is_child($node) {
$result = preg_match(/^$ancestors/,$node->ancestors,$match);
if ($node->ancestors == $this->ancestors) $result = false;
return $result;
}
}
class XML {
var $file;
var $tree = array();
var $nodes = array();
var $PIs;
var $format_body = font-family:Verdana;font-size:10pt;
var $format_bracket = color:blue;
var $format_element = font-family:Verdana;font-weight:bold;font-size:10pt;
var $format_attribute = font-family:Courier;font-size:10pt;
var $format_data = font-size:12pt;
var $format_attribute_name = color:#444444;
var $format_attribute_value = font-family:Courier;font-size:10pt;color:red;
var $format_blanks =
function XML($filename) {
$this->file = $filename;
$xml_parser = xml_parser_create();
xml_set_object($xml_parser,&$this);
xml_set_element_handler($xml_parser,startElement,endElement);
xml_set_character_data_handler($xml_parser,characterData);
xml_set_processing_instruction_handler ($xml_parser,process_instruction);
# Why should one want to use case-folding with XML? XML is case-sensitiv,I think this is nonsense
xml_parser_set_option($xml_parser,XML_OPTION_CASE_FOLDING,false);
if (!($fp = @fopen($this->file,r))) {
die(print(Couldn't open file: $this->file\n));
}
while ($data = fread($fp,4096)) {
if (!xml_parse($xml_parser,$data,feof($fp))) {
die(sprintf(XML error: %s at line %d\n,xml_error_string(xml_get_error_code($xml_parser)),xml_get_current_line_number($xml_parser)));
}
}
}
function startElement($parser,$name,$attribs) {
# Adding the additional element to the tree,including attributes
$this->tree[] = $name;
$node = new Node($this->tree);
while (list($k,$v) = each($attribs)) {
$node->attributes[$k] = $v;
}
$this->nodes[] = $node;
}
function endElement($parser,$name) {
# Adding a new element,describing the end of the tag
# But only,if the Tag has CDATA in it!
# Check
if (count($this->nodes) >= 1) {
$prev_node = $this->nodes[count($this->nodes)-1];
if (strlen($prev_node->data) > 0 || $prev_node->name != $name) {
$this->tree[count($this->tree)-1] = /.$this->tree[count($this->tree)-1];
$this->nodes[] = new Node($this->tree,NULL);
} else {
# Adding a slash to the end of the prev_node
$prev_node->name = $prev_node->name./
$this->nodes[count($this->nodes)-1]->name = $this->nodes[count($this->nodes)-1]->name./
}
}
# Removing the element from the tree
array_pop($this->tree);
}
function characterData($parser,$data) {
$data = ltrim($data);
if ($data != ) $this->nodes[count($this->nodes)-1]->add_data($data);
}
function process_instruction($parser,$target,$data) {
if (preg_match(/xml:stylesheet/,$match) && preg_match(/type=\text\/xsl\/,$match)) {
preg_match(/href=\(.+)\/i,$this->PIs);
# print <b>found xls pi: $PIs[1]</b><br>\n
}
}
function print_nodes() {
# Printing the header
print <html><head><title>.$this->nodes[0]->name.</title></head>
print <body style=\.$this->format_body.\>\n
# Printing the XML Data
for ($i = 0; $i < count($this->nodes); $i++) {
$node = $this->nodes[$i];
# Checking: Empty element
if ($node->name[strlen($node->name)-1] == /) {
$end_char = /
$node->name = substr($node->name,strlen($node->name)-1);
} else {
$end_char =
}
# Writing whitespaces,but only if it's _no_ closing element that follows
# directly on it's opening element
if (!(/.$this->nodes[$i-1]->name == $node->name)) {
for ($j = 0; $j < $node->level(); $j++) echo $this->format_blanks;
}
echo <span style=\.$this->format_bracket.\><</span><span style=\.$this->format_element.\>.$node->name.</span>
if ($node->has_attributes()) {
$keys = array_keys($node->attributes);
for ($j = 0; $j < count($keys); $j++) {
printf( <span style=\%s\>%s=\</span><span style=\%s\>%s</span><span style=\%s\>\</span>,$this->format_attribute_name,$keys[$j],$this->format_attribute_value,$node->attributes[$keys[$j]],$this->format_attribute_name);
}
echo
}
echo <span style=\.$this->format_element.\>$end_char</span><span style=\.$this->format_bracket.\>></span>
if (strlen($node->data) > 0) echo <span style=\.$this->format_data.\>.ltrim($node->data).</span>
else echo <br>\n
}
# Printing the footer
print </body></html>\n
}
}
/*** 代码来自编程之家 jb51.cc(jb51.cc) ***/