经测试代码如下:
/**
* xml分析类
*
* @param
* @arrange (512.笔记) 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) ***/