分类:
2008-04-13 20:52:12
概述
在网上有许多php的XML教程,但是只有少数介绍如何使用DOM来解析XML。我想利用这个机会展示一下在PHP编程中除了广泛使用的SAX实现方式外,还有另一种选择。
DOM(Document Object Model,文档对象模型)和SAX(Simple API for XML,XML简单应用程序接口)在如何解析XML上有不同的方法。SAX引擎完全是事件驱动的。当它遇到一个标记时,它就调用一个适当的函数来处理它。这使得SAX非常快速和有效。然而他给你的感觉就象被套在一个没完没了的循环里面。你发现自己使用了太多的全局变量和条件语句。
另一方面,DOM方法稍稍对内存有些敏感。它把整个XML文档以层次化的结构方式装载到内存里。这就是说,所有的数据组成了一个家族树,它们对编程者来说都是可用的。这种方法更直观,更容易使用,也提供了更多的可读性。
为了使用DOM函数,你必需在配置PHP时,使用'--with-dom'参数。它们不是标准配置的组成部分,这里有一个简单的编译方式。
%> ./configure --with-dom --with-apache=../apache_1.3.12 %> make %> make install |
<?XML version="1.0"?> <book type="paperback"> <title>Red Nails</title> <price>$12.99</price> <author> <name first="Robert" middle="E" last="Howard"/> <birthdate>9/21/1977</birthdate> </author> </book> |
DomNode book | |-->DomNode title | | | |-->DomNode text | |-->DomNode price | | | |-->DomNode text | |-->DomNode author | |-->DomNode name | |-->DomNode birthdate | |-->DomNode text |
class DomNode properties: name content type methods: lastchild() children() parent() new_child( $name,$content ) getattr( $name ) setattr( $name,$value ) attributes() |
class DomDocument properties: version encoding standalone type methods: root() children() add_root( $node ) dtd() dumpmem() |
class DomDocument properties: version encoding standalone name content type attributes children |
class Attribute properties: name content methods: name() class Dtd properties: extid sysid name class Namespace |
<?php # 使用下面两个方法中的任一个,从一个字符串装载XML $doc = XMLdoc( $XMLstr ); $tree = XMLtree( $XMLstr ); # 从一个文件装载XML $doc = XMLdocfile( $XMLfile ); ?> |
<?php # 生成一个XML范例文档,以进行演示 $XMLstr = "<" . "?" . "XML version=\"1.0\"" . "?" . ">"; $XMLstr .= " <employee> <name>Matt</name> <position type=\"contract\">Web Guy</position> </employee> "; # 装载XML数据($doc成为一个DomDocument对象的实例) $doc = XMLdoc($XMLstr); # 得到根节点"employee" $employee = $doc->root(); # 得到employee节点的子节点("name","position") $nodes = $employee->children(); # 我们打算使用"position"节点 # 因此我们必需反复通过employee的子节点来搜索它 while ($node = array_shift($nodes)) { if ($node->name == "position") { $position = $node; break; } } # 得到position的类型属性 $type = $position->getattr("type"); # 得到被封闭在position标记中的文本 # 移动到position子节点的第一个子节点 # 译注:这里的用法可以参考第一部分“DOM如何构造XML”的最后一段。 $text_node = array_shift($position->children()); # 访问这个文本节点的内容属性 $text = $text_node->content; # 输出position和type echo "position: $text<BR>"; echo "type: $type"; ?> |
position: Web Guy type: contract |
<employee> <name>Matt</name> <position type="contract">Web Guy</position> </employee> |
<?XML version="1.0"?> <employees company="zoomedia.com"> <employee> <name>Matt</name> <position type="contract">Web Guy</position> </employee> <employee> <name>George</name> <position type="full time">Mad Hacker</position> </employee> <employee> <name>Wookie</name> <position type="part time">Hairy SysAdmin</position> </employee> </employees> |
<?php # 遍历一个节点数组,寻找一个文本节点,并返回它的内容 function get_content($parent) { $nodes = $parent->children(); while($node = array_shift($nodes)) if ($node->type == XML_TEXT_NODE) return $node->content; return ""; } # 得到一个特定节点的内容 function find_content($parent,$name) { $nodes = $parent->children(); while($node = array_shift($nodes)) if ($node->name == $name) return get_content($node); return ""; } # 得到一个特定节点的属性 function find_attr($parent,$name,$attr) { $nodes = $parent->children(); while($node = array_shift($nodes)) if ($node->name == $name) return $node->getattr($attr); return ""; } # 载入XML文档 $doc = XMLdocfile("employees.XML") or die("What employees?"); # 得到根节点(employees) $root = $doc->root(); # 得到employees的子节点数组,它包含了每一个employee节点 $employees = $root->children(); # 在数组中移动,输出一些emloyee数据 while($employee = array_shift($employees)) { if ($employee->type == XML_TEXT_NODE) continue; $name = find_content($employee,"name"); $pos = find_content($employee,"position"); $type = find_attr($employee,"position","type"); echo "$name the $pos, $type employee<br>"; } ?> |
Matt the Web Guy, contract employee George the Mad Hacker, full time employee Wookie the Hairy SysAdmin, part time employee |
<?php # 生成子节点的函数 function make_node($parent,$name,$content) { # 增加一个新子节点到父节点 $parent->new_child($name,$content); # 返回新增加的子节点 return $parent->lastchild(); } # 载入XML文件,得到根节点 $doc = XMLdocfile("employees.XML") or die("Do you even have any employees?"); $root = $doc->root(); # 赋予新employee(雇员)一个名字 $newguy = make_node($root,"employee",""); # 增加新成员的名字 make_node($newguy,"name","New Guy"); # 增加他的职位 $position = make_node($newguy,"position","Backup Gnome"); # 设置'type'属性 $position->setattr("type","intern"); # 将我们改变过的XML文档输出到浏览器 echo $doc->dumpmem(); ?> |