资讯·论坛·笑话大全·QQ表情·设为首页
发新话题
打印

[综合类] php的xml分析函数

php的xml分析函数

首先我得承认我喜欢计算机标准。如果每个人都遵从这个行业的标准,互联网将会是一个更好的媒体。使用标准化的数据交换格式才能使开放的和独立于平台的计算模式切实可行。这就是我作为XML爱好者的原因。
* X  v$ p% E) D) Z
" J  V6 t3 I; }3 h5 f5 ~* b; G7 u我爱电脑技术社区--打造最好的电脑技术自学交流平台幸运的是,我最喜爱的脚本语言不但支持XML而且对其支持正不断加强。PHP可以让我迅速将XML文档发布到互联网上,收集XML文档的统计信息,将XML文档转换成其它格式。例如,我时常用PHP的XML处理能力来管理我用XML所写的文章和书。 我爱电脑技术论坛0 O" ?- k, a" w: ?8 q- V% c
www.520diannao.com# K7 o$ f" h; w+ ~
本文中,我将讨论任何用PHP内建的Expat解析器来处理XML文档。通过范例,我将演示Expat的处理方法。同时,范例可以告诉你如何:
# k1 X: z3 m/ O! R; i5 Q* z打造最好的电脑自学交流论坛
! V$ a# l+ O5 v7 ?$ H我爱电脑技术社区--打造最好的电脑技术自学交流平台建立你自己的处理函数  
* t* d) F0 l; v- Q. t- J将XML文档转换成你自己的PHP数据结构 www.520diannao.com0 J! J, E% ~7 @
www.520diannao.com  [( h  o) @8 ^; D1 L
介绍Expat
% B6 x! K! K7 B9 l/ E+ G0 ^  k电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站
! s0 u* J. q( I- l! n) e我爱电脑技术社区--打造最好的电脑技术自学交流平台XML的解析器,同样称为XML处理器,可以使程序访问XML文档的结构和内容。Expat是PHP脚本语言的XML解析器。它同时也运用在其它项目中,例如Mozilla、Apache和Perl。
8 y1 ]* S8 K( _9 T0 w9 ?$ L$ @我爱电脑技术论坛
: G4 Y8 ~. F1 _) t% d/ a我爱电脑技术论坛什么是基于事件的解析器?
# r( A7 x7 C/ R0 |  C9 _3 [0 m电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站打造最好的电脑自学交流论坛6 S" m6 m3 h+ n1 W% m
XML解析器的两种基本类型:
, M, L$ o4 }% L1 Zwww.520diannao.com
, `  T! n% }1 [& f/ ]我爱电脑技术论坛基于树型的解析器:将XML文档转换成树型结构。这类解析器分析整篇文章,同时提供一个API来访问所产生树的每个元素。其通用的标准为DOM(文档对象模式)。  打造最好的电脑自学交流论坛- Z- Y; {9 O, A5 q3 E5 Y
基于事件的解析器:将XML文档视为一系列的事件。当一个特殊事件发生时,解析器将调用开发者提供的函数来处理。  www.520diannao.com6 I6 B8 M: p7 w2 ?0 J
基 于事件的解析器有一个XML文档的数据集中视图,也就是说它集中在XML文档的数据部分,而不是其结构。这些解析器从头到尾处理文档,并将类似于-元素的 开始、元素的结尾、特征数据的开始等等-事件通过回调(callback)函数报告给应用程序。以下是一个"Hello-World"的XML文档范例: 1 r- Q' F" d8 }3 n% U5 M/ z+ P% v0 S

; w) V6 J" P* K2 J打造最好的电脑自学交流论坛<greeting>  
- q' G8 @  o$ a4 y0 q我爱电脑技术社区--打造最好的电脑技术自学交流平台Hello World  
! q+ r- g* z& l2 w我爱电脑技术论坛</greeting>  打造最好的电脑自学交流论坛) o: s) s( n. ^8 p! z, g! Q4 g

4 ]; w, E4 L4 B* V+ X我爱电脑技术社区--打造最好的电脑技术自学交流平台基于事件的解析器将报告为三个事件:
4 E, t5 Q, A" J" n4 k电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站www.520diannao.com  Z3 b" g, N+ K: |# ~' b
开始元素:greeting  
' p5 ^; G  b. Y2 |3 r电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站CDATA项的开始,值为:Hello World  电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站# Q( \1 d3 ?1 Y& {0 o
结束元素:greeting  打造最好的电脑自学交流论坛& H# a4 r" Q" N6 ^8 c
不像基于树型的解析器,基于事件的解析器不产生描述文档的结构。在CDATA项中,基于事件的解析器不会让你得到父元素greeting的信息。
# G9 S+ ]& P$ X- x我爱电脑技术社区--打造最好的电脑技术自学交流平台然而,它提供一个更底层的访问,这就使得可以更好地利用资源和更快地访问。通过这种方式,就没有必要将整个文档放入内存;而事实上,整个文档甚至可以大于实际内存值。

TOP

Expat就是这样的一种基于事件的解析器。当然如果使用Expat,必要时它一样可以在PHP中生成完全的原生树结构。
8 H) v+ z9 J/ U7 A2 C0 {$ Z我爱电脑技术社区--打造最好的电脑技术自学交流平台
. d6 M- O" d9 P% r上面Hello-World的范例包括完整的XML格式。但它是无效的,因为既没有DTD(文档类型定义)与其联系,也没有内嵌DTD。 打造最好的电脑自学交流论坛% \) L, e1 c: r0 B
www.520diannao.com" ]) ?. d$ O" u, D0 r
对于Expat,这并没有区别:Expat是一个不检查有效性的解析器,因此忽略任何与文档联系的DTD。但应注意的是文档仍然需要完整的格式,否则Expat(和其他符合XML标准的解析器一样)将会随着出错信息而停止。
- f3 J% f. Y- @( s打造最好的电脑自学交流论坛% g* c' L3 D7 Y/ A. h( ?! I9 q
作为不检查有效性的解析器,Exapt的快速性和轻巧性使其十分适合互联网程序。 电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站  h7 D1 C0 v& W8 q/ e) A' Y( _$ n

) L0 T5 J2 X- n! i/ Q打造最好的电脑自学交流论坛编译Expat
9 j; ~+ X1 ?8 v电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站我爱电脑技术社区--打造最好的电脑技术自学交流平台0 C( [" _; q: k  l9 r
Expat可以编译进PHP3.0.6版本(或以上)中。从Apache1.3.9开始,Expat已经作为Apache的一部分。在Unix系统中,通过-with-xml选项配置PHP,你可以将其编译入PHP。
9 v! N6 U4 x4 `电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站我爱电脑技术社区--打造最好的电脑技术自学交流平台; r# H- w8 c4 a1 Z% h
如果你将PHP编译为Apache的模块,而Expat将默认作为Apache的一部分。在Windows中,你则必须要加载XML动态连接库。
* K; k+ T& Q+ }1 Z7 ^$ B我爱电脑技术论坛0 n" K% J- Q( I# {
XML范例:XMLstats
4 ?* O1 g- ^+ Z, j6 @0 j/ g打造最好的电脑自学交流论坛
7 ^) X+ H; @, n  N我爱电脑技术论坛了解Expat的函数的一个办法就是通过范例。我们所要讨论的范例是使用Expat来收集XML文档的统计数据。
9 B$ u- M: Y1 Y$ Qwww.520diannao.com
9 I; j/ ]* y' ~& N我爱电脑技术论坛对于文档中每个元素,以下信息都将被输出: 我爱电脑技术社区--打造最好的电脑技术自学交流平台& B/ C2 l. I* n' v! x

7 @. X1 B% A% R! hwww.520diannao.com该元素在文档中使用的次数  我爱电脑技术论坛5 d/ [, c- j9 r6 \/ K% i
该元素中字符数据的数量  电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站% ]) t. S& H; `; Z' M- s
元素的父元素  
/ C+ z* a# \8 L5 b7 l元素的子元素  我爱电脑技术社区--打造最好的电脑技术自学交流平台- r: K7 u1 o( E1 x
注意:为了演示,我们利用PHP来产生一个结构来保存元素的父元素和子元素 : b$ c9 ~. c- B$ Q. G2 V! g
我爱电脑技术社区--打造最好的电脑技术自学交流平台7 t1 A) J& P8 x3 |& m+ g
准备
2 A3 ?# K  l. j, u5 C1 {. `( _: n4 e1 i
用 于产生XML解析器实例的函数为xml_parser_create()。该实例将用于以后的所有函数。这个思路非常类似于PHP中MySQL函数的连接 标记。在解析文档前,基于事件的解析器通常要求你注册回调函数-用于特定的事件发生时调用。Expat没有例外事件,它定义了如下七个可能事件:

TOP

对象 XML解析函数 描述
6 p7 v( l0 a6 \9 c) Z) N9 f0 n8 Owww.520diannao.com
9 v8 m4 r' C/ i. f4 }$ Owww.520diannao.com元素 xml_set_element_handler() 元素的开始和结束
0 @" H( u0 n! C( T) v- L" W电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站
5 S5 r; T) ?5 B& U5 E" {& P" C  O打造最好的电脑自学交流论坛字符数据 xml_set_character_data_handler() 字符数据的开始 www.520diannao.com* V$ ]2 o0 L$ W, m  ]

7 S: p" Z6 M6 A; g9 Q8 [8 }电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站外部实体 xml_set_external_entity_ref_handler() 外部实体出现
4 v) w" x( b* c2 a: v  A我爱电脑技术社区--打造最好的电脑技术自学交流平台我爱电脑技术论坛- u1 Y, \5 F6 ?- g7 S# }" E
未解析外部实体 xml_set_unparsed_entity_decl_handler() 未解析的外部实体出现 我爱电脑技术论坛' S6 S) `/ e# E+ k1 M, q

6 |. y; D. u8 N/ C9 n" w% R处理指令 xml_set_processing_instruction_handler() 处理指令的出现
# H& V5 n- P( Xwww.520diannao.com3 k- f: ^8 {) w4 D+ Q- v# M7 Z% @
记法声明 xml_set_notation_decl_handler() 记法声明的出现 打造最好的电脑自学交流论坛4 Q. M6 W4 ~  V+ {) ^5 D

3 k; }/ _4 s; ~0 ?1 \, ]我爱电脑技术论坛默认 xml_set_default_handler() 其它没有指定处理函数的事件
) {  t9 X) b& G: H5 i; K我爱电脑技术论坛打造最好的电脑自学交流论坛/ w* S" X  h' d, |- U4 a
所有的回调函数必须将解析器的实例作为其第一个参数(此外还有其它参数)。
/ r+ l8 L4 d6 B* |4 Z$ N( A0 l4 i打造最好的电脑自学交流论坛
. W2 e1 t/ I) {3 Q4 Q7 O9 k# ~0 _www.520diannao.com对于本文最后的范例脚本。你需要注意的是它既用到了元素处理函数又用到了字符数据处理函数。元素的回调处理函数通过xml_set_element_handler()来注册。
8 G2 K# M0 L6 }; \7 e2 M$ _( K5 i1 h打造最好的电脑自学交流论坛我爱电脑技术论坛+ Q+ m# u- l0 D9 i! _- V! H
这个函数需要三个参数:
% y6 g7 ^* ]2 N( g1 r4 \9 H) m: p
9 w3 z4 m7 E) `0 s  Z0 e4 \电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站解析器的实例  电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站/ e% v! j8 W; \* y2 I- M
处理开始元素的回调函数的名称  我爱电脑技术社区--打造最好的电脑技术自学交流平台4 w, _5 G- v  v0 S, x, c5 e2 a2 d
处理结束元素的回调函数的名称  
, F' N+ [- ~! x+ l; b9 ?" k1 Q4 J我爱电脑技术论坛当开始解析XML文档时,回调函数必须存在。它们必须定义为与PHP手册中所描述的原型一致。
" H+ s$ @2 F! N$ X我爱电脑技术论坛我爱电脑技术社区--打造最好的电脑技术自学交流平台+ C. U2 ^6 K) C' r$ E
例如,Expat将三个参数传递给开始元素的处理函数。在脚本范例中,其定义如下: 打造最好的电脑自学交流论坛- s* `$ z. m; Q/ s' C$ v

; @$ h4 c$ d2 Y+ J6 ]7 K我爱电脑技术论坛function start_element($parser, $name, $attrs)  
" F& T! p& `7 ]; i9 Z+ u我爱电脑技术论坛
; i) r0 f$ q1 G6 \3 r7 b打造最好的电脑自学交流论坛第一个参数是解析器标示,第二个参数是开始元素的名称,第三参数为包含元素所有属性和值的数组。 % o! x' [5 D) I- m/ w* w  H

( z6 O/ i9 H2 w7 [( M' P) f打造最好的电脑自学交流论坛一旦你开始解析XML文档,Expat在遇到开始元素是都将调用你的start_element()函数并将参数传递过去。 我爱电脑技术论坛0 w& d9 [6 y  x6 v+ F

+ n" q# L: K5 q9 f' D& j# I电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站XML的Case Folding选项 % d8 o. Q. i# M& e8 B& d

/ x$ {( F* b* v+ v* E* w电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站用xml_parser_set_option ()函数将Case folding选项关闭。这个选项默认是打开的,使得传递给处理函数的元素名自动转换为大写。但XML对大小写是敏感的(所以大小写对统计XML文档是非 常重要的)。对于我们的范例,case folding选项必须关闭。

TOP

解析文档
1 W# d6 _# T4 z% u0 Q# z9 p" f& _# m电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站www.520diannao.com' z( _- [7 y# g( h5 _. b! L+ j1 l
在完成所有的准备工作后,现在脚本终于可以解析XML文档: www.520diannao.com- B3 b; x* B; F5 m# Z2 D5 o
' v: n$ @; v) w- m. T
Xml_parse_from_file(),一个自定义的函数,打开参数中指定的文件,并以4kb的大小进行解析  
3 L2 [- N9 e0 ~  K5 h' _( [: v" h我爱电脑技术社区--打造最好的电脑技术自学交流平台xml_parse()和xml_parse_from_file()一样,当发生错误时,即XML文档的格式不完全时,将会返回false。  ) y6 q+ A# b  K! Y+ u
你可以使用xml_get_error_code()函数来得到最后一个错误的数字代码。将此数字代码传递给xml_error_string()函数即可得到错误的文本信息。  打造最好的电脑自学交流论坛$ m$ a9 z1 f- D# z$ m
输出XML当前的行数,使得调试更容易。  www.520diannao.com$ t# A, I8 a( G' L. O
在解析的过程中,调用回调函数。  www.520diannao.com7 }1 u& \* L8 `# s, L# w
描述文档结构
" S8 t& g; [) A8 Z* k# t, J! e电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站我爱电脑技术论坛( N# L0 v3 R, t/ o; Z# ^
当解析文档时,对于Expat需要强调问题的是:如何保持文档结构的基本描述?
0 |, S+ K9 q3 b; _, w打造最好的电脑自学交流论坛我爱电脑技术论坛4 e! @5 Z% I6 W- y0 ]& k
如前所述,基于事件的解析器本身并不产生任何结构信息。
$ P! C" q7 H# y* g打造最好的电脑自学交流论坛我爱电脑技术社区--打造最好的电脑技术自学交流平台% r6 w& q9 V; ?
不 过标签(tag)结构是XML的重要特性。例如,元素序列<book><title>表示的意思不同于< figure><title>。也就是说,任何作者都会告诉你书名和图名是没有关系的,虽然它们都用到"title"这个术语。因此, 为了更有效地使用基于事件的解析器处理XML,你必须使用自己的栈(stacks)或列表(lists)来维护文档的结构信息。
' s, G8 u8 s0 X, I: E1 Uwww.520diannao.comwww.520diannao.com" b8 V) |2 x7 P) y5 p: u; Z
为了产生文档结构的镜像,脚本至少需要知道目前元素的父元素。用Exapt的API是无法实现的,它只报告目前元素的事件,而没有任何前后关系的信息。因此,你需要建立自己的栈结构。
9 a; S; M% a$ J0 {- |8 G$ r我爱电脑技术论坛电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站6 n% x+ H4 g( _
脚本范例使用先进后出(FILO)的栈结构。通过一个数组,栈将保存全部的开始元素。对于开始元素处理函数,目前的元素将被array_push()函数推到栈的顶部。相应的,结束元素处理函数通过array_pop()将最顶的元素移走。 我爱电脑技术论坛& A* c8 O: Y) A' |- b( S2 `
打造最好的电脑自学交流论坛4 [( d( T9 `8 H& e9 o8 v' B3 {6 W/ j
对于序列<book><title></title></book>,栈的填充如下: ; l# o+ z5 o6 z" i" ]% D8 U6 k  z
www.520diannao.com2 Y7 p6 O# u' G
开始元素book:将"book"赋给栈的第一个元素($stack[0])。  
9 c2 L5 f) B- h- h7 Q% X电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站开始元素title:将"title"赋给栈的顶部($stack[1])。  
2 c% Q. m+ u* J! U! P) R% D; |( w6 d结束元素title:从栈中将最顶部的元素移去($stack[1])。  电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站2 x$ y& S: f" T9 k/ F. b( E7 Q
结束元素title:从栈中将最顶部的元素移去($stack[0])。  + {/ C1 s% O: S; [0 S; A9 \- ?2 _
PHP3.0通过一个$depth变量手动控制元素的嵌套来实现范例。这就使脚本看起来比较复杂。PHP4.0通过array_pop()和array_push()两个函数来使脚本看起来更简洁。
1 x3 z* x; m* y% s- T4 [www.520diannao.com
) P7 O' a& C3 m  Z! ?; @收集数据 我爱电脑技术社区--打造最好的电脑技术自学交流平台9 Y3 [. H% y5 [+ _! D

' F' i# f# ?/ N1 t8 w我爱电脑技术论坛为了收集每个元素的信息,脚本需要记住每个元素的事件。通过使用一个全局的数组变量$elements来保存文档中所有不同的元素。数组的项目是元素类的实例,有4个属性(类的变量)

TOP

$count -该元素在文档中被发现的次数  
) S6 F: R* _9 U1 `) S- Q% b4 _我爱电脑技术社区--打造最好的电脑技术自学交流平台$chars -元素中字符事件的字节数  - A: s1 `' `7 J9 V
$parents -父元素  打造最好的电脑自学交流论坛* v; B1 q/ b; n9 i/ W
$childs - 子元素  电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站+ H! D. y% i! g( z, j# m& @
正如你所看到的,将类实例保存在数组中是轻而易举的。
+ p5 t$ i7 I0 D2 ^( i) d# I$ v
8 |2 n  J+ Y" h1 X我爱电脑技术论坛注意:PHP的一个特性是你可以通过while(list() = each())loop遍历整个类结构,如同你遍历整个相应的数组一样。所有的类变量(当你用PHP3.0时还有方法名)都以字符串的方式输出。
& \. F" N! V& o$ pwww.520diannao.com
" S# a  T' Y9 t! N" X/ D8 n当发现一个元素时,我们需要增加其相应的记数器来跟踪它在文档中出现多少次。在相应的$elements项中的记数元素也要加一。
: w+ y9 U. `* ]电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站我爱电脑技术论坛% u  c$ ]2 `& \
我们同样要让父元素知道目前的元素是它的子元素。因此,目前元素的名称将会加入到父元素的$childs数组的项目中。最后,目前元素应该记住谁是它的父元素。所以,父元素被加入到目前元素$parents数组的项目中。
) v# b7 W! k4 w2 V6 O, x4 `! ?$ y" g0 N, p5 N9 S+ T1 Y' l1 E
显示统计信息
& F4 f! V2 F' ^% Y2 ^我爱电脑技术论坛
; b1 o" |) `- E剩下的代码在$elements数组和其子数组中循环显示其统计结果。这就是最简单的嵌套循环,尽管输出正确的结果,但代码既不简洁又没有任何特别的技巧,它仅仅是一个你可能每天用他来完成工作的循环。
6 k6 I' H, o9 b9 j/ f我爱电脑技术社区--打造最好的电脑技术自学交流平台
% G  ?/ ^4 e5 ~  qwww.520diannao.com脚本范例被设计为通过PHP的CGI方式的命令行来调用。因此,统计结果输出的格式为文本格式。如果你要将脚本运用到互联网上,那么你需要修改输出函数来产生HTML格式。
, \. H" x/ h( l* P( E2 ~打造最好的电脑自学交流论坛
; X+ Q! L/ U( h; ]# C' l2 j& wwww.520diannao.com总结
8 q$ k9 u+ |- e我爱电脑技术社区--打造最好的电脑技术自学交流平台
4 b9 w) C$ z$ G电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站Exapt是PHP的XML解析器。作为基于事件的解析器,它不产生文档的结构描述。但通过提供底层访问,这就使得可以更好地利用资源和更快地访问。 www.520diannao.com" r2 J4 L+ f9 u  E4 z0 u2 H
& e5 f7 r) W4 J' g& n0 U
作为一个不检查有效性的解析器,Expat忽略与XML文档连接的DTD,但如果文档的格式不完整,它将会随着出错信息而停止。
2 Q" X# x' B1 L9 R/ }2 E. r3 A我爱电脑技术论坛
  w6 Q: N" |) y5 N5 c我爱电脑技术社区--打造最好的电脑技术自学交流平台提供事件处理函数来处理文档  
5 z5 H8 [4 ?! Y8 `" l) t+ ^建立自己的事件结构例如栈和树来获得XML结构信息标记的优点。  我爱电脑技术社区--打造最好的电脑技术自学交流平台7 G: m/ B  j! X4 r, v3 z
每天都有新的XML程序出现,而PHP对XML的支持也不断加强(例如,增加了支持基于DOM的XML解析器LibXML)。 我爱电脑技术论坛- o2 `! Q- T5 A/ M
www.520diannao.com7 \9 U! }) Q( }  _; P4 S
有了PHP和Expat,你就可以为即将出现的有效、开放和独立于平台的标准作准备。
) i9 X+ \) [) f; o$ y! d' e我爱电脑技术社区--打造最好的电脑技术自学交流平台打造最好的电脑自学交流论坛7 J7 Q+ d# U" f# e6 y! b
范例
+ O% U0 }8 s1 K& a9 U+ C- ewww.520diannao.com
  r6 m$ A  E; o. R, |: ^电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站<?  
, }. c- u; j7 g4 J3 Z" R( _我爱电脑技术论坛/*****************************************************************************

TOP

名称:XML解析范例:XML文档信息统计
( ^- ~$ q" O1 j; x3 I0 v5 e电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站* 描述  我爱电脑技术论坛: p1 q+ D6 E+ q  }* o  f
* 本范例通过PHP的Expat解析器收集和统计XML文档的信息(例如:每个元素出现的次数、父元素和子元素  
) `+ {( P3 u7 ?" @; d3 ]2 A9 v( ~) {我爱电脑技术社区--打造最好的电脑技术自学交流平台* XML文件作为一个参数 ./xmlstats_PHP4.php3 test.xml  
+ Z: O% n4 S8 m$ o+ |. z6 S$ G我爱电脑技术论坛* $Requires: Expat 要求:Expat PHP4.0编译为CGI模式  
$ t' R* h' s+ {/ j/ P, ~www.520diannao.com*****************************************************************************/  
& n7 ^  B% |# V; w! e4 a9 W/ u电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站www.520diannao.com0 }$ S6 X% X+ d
// 第一个参数是XML文件 www.520diannao.com1 ~9 q. s  L5 z! ?
$file = $argv[1];  ! y5 q/ \5 H$ a8 d9 ~; O

3 W" X% b, ]5 P0 _) ~我爱电脑技术论坛// 变量的初始化 www.520diannao.com9 s( M/ V1 S9 y7 F
$elements = $stack = array();  
9 H! R+ y4 |' o! w: _& ?1 m# L我爱电脑技术社区--打造最好的电脑技术自学交流平台$total_elements = $total_chars = 0;  我爱电脑技术社区--打造最好的电脑技术自学交流平台6 `- ~* r* ~! u$ I) {& @' e

, Z+ @8 c1 @+ m' \, E& K打造最好的电脑自学交流论坛// 元素的基本类 www.520diannao.com) k; c/ l/ y( n8 i( `' w
class element  打造最好的电脑自学交流论坛# y9 _: X' J9 @+ d) y: d
{  我爱电脑技术论坛0 J4 A/ ?* R3 z  T% \6 a; o5 f
var $count = 0;  
% G, O0 m8 l8 I9 f6 Twww.520diannao.comvar $chars = 0;  打造最好的电脑自学交流论坛" P! f- E5 h; ?& ^1 U. Z
var $parents = array();  
6 X- `1 ?& Y" L- p. P我爱电脑技术论坛var $childs = array();  
* F6 D* k% O) \) P% f" wwww.520diannao.com}  
9 t! V: v+ D4 g2 _( x. q& e% e3 l我爱电脑技术论坛
, J( O6 u  u/ @  iwww.520diannao.com// 解析XML文件的函数
% m. {* H( t1 ]% j, p+ T6 M我爱电脑技术论坛function xml_parse_from_file($parser, $file)  打造最好的电脑自学交流论坛7 v0 S* n* w. c% \  n. P. I! U  g7 y
{  打造最好的电脑自学交流论坛2 }* N. |5 J$ v# I& ~) f/ S
if(!file_exists($file))  6 A# d$ I. Z4 {# B. r, Q: D
{  电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站$ C) Z: k* C- h1 h" n, r7 N" m7 @
die("Can't find file "$file".");  
. `  l  C5 f; x- G}  打造最好的电脑自学交流论坛4 C; |( u$ M  O7 L7 K; e

8 t8 k7 P: b) ~2 b" {if(!($fp = @fopen($file, "r")))  
/ x3 s( W. Y8 e2 G) `" h0 d我爱电脑技术社区--打造最好的电脑技术自学交流平台{  
; W2 G; K0 r; N" ]8 H9 Xdie("Can't open file "$file".");  
9 z+ x! _) j, F( s; G我爱电脑技术社区--打造最好的电脑技术自学交流平台}  
+ R* @+ A( G5 s7 U. r1 h- N3 B* S
1 P" v; _% ^. Q- l$ X! H我爱电脑技术社区--打造最好的电脑技术自学交流平台while($data = fread($fp, 4096))  我爱电脑技术论坛$ ?8 j2 _. _5 L5 w
{  电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站5 i1 F& y% w9 }5 `' B5 T
if(!xml_parse($parser, $data, feof($fp)))  电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站) e4 _* Y( K. r9 t" u
{  
! }1 K: W" ?2 {0 }, N6 A+ E电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站return(false);  www.520diannao.com" V; H# ~" J* r
}  
% y' y+ j& @  @3 A. i/ y我爱电脑技术论坛}  
  [8 C9 k( E' Y- K% ~/ uwww.520diannao.com
  a7 p- d0 B& r. p7 }% @. }( C# K我爱电脑技术社区--打造最好的电脑技术自学交流平台fclose($fp);  
& q; {2 ^" k7 U, ^我爱电脑技术论坛电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站1 ~. `3 a$ X, E# W
return(true);  
* `. S8 R8 F# I6 T/ {www.520diannao.com}  
+ P6 K/ S. T( e! W" D: N1 j* L我爱电脑技术社区--打造最好的电脑技术自学交流平台8 G5 j) E3 b5 z0 A+ c, O/ }
// 输出结果函数(方框形式) 打造最好的电脑自学交流论坛2 S7 |1 ]% y& x- G+ Q( x9 J
function print_box($title, $value)  
' r' o* \" E6 ]{  www.520diannao.com: u4 @% l8 H, }: e$ J* I/ S. \2 |3 d# x( h
printf("n+%'-60s+n", "");  我爱电脑技术论坛9 ~' {0 H3 m* j/ U* b5 a% N8 O
printf("|%20s", "$title:");  
7 u, @( z: ?7 J, Q1 a: Cwww.520diannao.comprintf("%14s", $value);  
- l- ?1 l$ U5 T% U- q: eprintf("%26s|n", "");  打造最好的电脑自学交流论坛' F# f/ ^% |$ b' N& i
printf("+%'-60s+n", "");  我爱电脑技术社区--打造最好的电脑技术自学交流平台" s' b' a/ Y% a
}

TOP

// 输出结果函数(行形式)
6 h/ ?0 y; X4 v) Ufunction print_line($title, $value)  
6 Y9 Q! S1 T5 n  ]7 ]( d我爱电脑技术论坛{  我爱电脑技术社区--打造最好的电脑技术自学交流平台4 w  N3 a5 a' O9 Q- R& N
printf("%20s", "$title:");  
) t3 l% o8 [4 |/ s. X7 w( R/ @2 ~我爱电脑技术社区--打造最好的电脑技术自学交流平台printf("%15sn", $value);  
/ w( t2 @, P- F# B  `$ z我爱电脑技术社区--打造最好的电脑技术自学交流平台}  
3 U4 }/ _1 e2 @- W9 q! v% X: F: i) u0 Y! C( C4 W
// 排序函数 打造最好的电脑自学交流论坛9 J0 z$ ^' X- J% b& m
function my_sort($a, $b)  打造最好的电脑自学交流论坛$ T  S/ L% J% y4 p8 `5 a/ P/ j
{  
- {0 ^! N, r% c% c- b* Z$ ?www.520diannao.comreturn(is_object($a) && is_object($b) ? $b->count - $a->count: 0);  
8 W, W, n9 g$ z' P" q5 l, c9 ]0 d电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站}  我爱电脑技术社区--打造最好的电脑技术自学交流平台7 ?" Q1 ^( n- u1 ]( S+ J$ H: g
www.520diannao.com! W% w& r! m4 g5 a
function start_element($parser, $name, $attrs)  我爱电脑技术社区--打造最好的电脑技术自学交流平台+ X- B/ e/ E' `' K/ ?2 D
{  我爱电脑技术社区--打造最好的电脑技术自学交流平台, O# X/ Q5 |$ V! e
global $elements, $stack;  0 G2 ?1 d1 \. U/ c$ q4 S

3 n, u$ R; y$ d7 s电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站// 元素是否已在全局$elements数组中?
: ]+ E. r% f# T) ?/ \我爱电脑技术论坛if(!isset($elements[$name]))  打造最好的电脑自学交流论坛' c. ~% r8 _7 e6 z
{  电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站6 P2 e! S" r( Q
// 否-增加一个元素的类实例
2 ], M, k. }" a+ A; n8 i电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站$element = new element;  
4 N) {9 Q% v. _! ]7 [2 y* Qwww.520diannao.com$elements[$name] = $element;  
# p6 w  I2 R( ^9 cwww.520diannao.com}  
6 x8 _. Q8 b/ f3 i2 u% t$ `www.520diannao.com
" a6 {- N1 ^  B0 K$ u( X- ~$ o电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站// 该元素的记数器加一
) O6 m7 ~( P. U2 A! X打造最好的电脑自学交流论坛$elements[$name]->count++;  我爱电脑技术论坛4 C" @* y" c, E

! \- D4 l/ g! nwww.520diannao.com// 是否有父元素? www.520diannao.com7 E4 k, W* c6 A/ K0 B. U8 d% U
if(isset($stack[count($stack)-1]))  我爱电脑技术社区--打造最好的电脑技术自学交流平台3 s( Q1 ?2 H3 B* T9 V
{  我爱电脑技术论坛4 b4 w$ }9 E: A
// 是-将父元素赋给$last_element 电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站2 z0 A/ I+ G  x6 R3 `
$last_element = $stack[count($stack)-1];  我爱电脑技术论坛; ]3 `* g, W* Z/ \1 H
www.520diannao.com9 y3 f; ?" X: k1 n
// 如果目前元素的父元素数组为空,初始化为0 www.520diannao.com2 _; W/ ^3 @4 z( x
if(!isset($elements[$name]->parents[$last_element]))  
$ G/ u% ~. o# N" B{  4 P  \- a$ x7 Q9 y8 |; C9 X
$elements[$name]->parents[$last_element] = 0;  : \/ i( O7 l2 a1 y  H% H, ^
}  
% I* X, f5 x3 f: N" ?; ywww.520diannao.comwww.520diannao.com+ o5 K5 ^' b3 r
// 该元素的父元素记数器加一
: `9 I  T0 @$ e  W1 U( E. r电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站$elements[$name]->parents[$last_element]++;  
- q3 @  s* l% M5 O$ t7 {我爱电脑技术社区--打造最好的电脑技术自学交流平台电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站7 y- j" Y; y2 K6 Z% D1 q
// 如果目前元素的父元素的子元素数组为空,初始化为0
1 f& _( Q& Q4 Q9 F5 b! l1 H/ \我爱电脑技术论坛电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站0 v7 x$ \: r% A" z
if(!isset($elements[$last_element]->childs[$name]))  电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站* v6 I! ^; j' w# |6 Q
{  我爱电脑技术社区--打造最好的电脑技术自学交流平台6 }+ l. ^- L4 L
$elements[$last_element]->childs[$name] = 0;  
) P% X8 S5 |1 C: C% @& k# n我爱电脑技术论坛}

TOP

// 该元素的父元素的子元素记数器加一
+ x( G8 z5 _4 y' u8 u+ a8 z- @电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站$elements[$last_element]->childs[$name]++;  我爱电脑技术社区--打造最好的电脑技术自学交流平台0 h2 f$ W' A3 h; o+ W
}  我爱电脑技术论坛) `/ k4 u" R$ h, J! D- p7 j8 k

. W) `8 c6 y- F' [1 n1 E/ l// 将目前的元素加入到栈中 我爱电脑技术社区--打造最好的电脑技术自学交流平台+ A! b% Y' o, w
array_push($stack, $name);  电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站1 t8 {. n2 l5 L5 U& j
}  
: m, o% c' ?; ~我爱电脑技术论坛
9 ^$ F7 H* }# z8 Ofunction stop_element($parser, $name)  
5 O  v. @( f% c1 ^0 F电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站{  
  L' O+ m0 v0 N( U+ b8 U  fglobal $stack;  
5 }  m" n0 k8 y9 q. u电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站
: {7 L6 i: J; ?6 q* D我爱电脑技术社区--打造最好的电脑技术自学交流平台// 从栈中将最顶部的元素移去
; |9 A2 L% ~$ @' R我爱电脑技术社区--打造最好的电脑技术自学交流平台array_pop($stack);  
& {3 s0 z# I* F! C5 Y5 p$ k我爱电脑技术论坛}  电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站0 M1 J* Z! k1 X7 Q% K9 {0 |

7 b* P1 u. J+ Q2 p$ Q电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站function char_data($parser, $data)  www.520diannao.com1 I8 j( ?$ T* T3 _
{  我爱电脑技术社区--打造最好的电脑技术自学交流平台5 H; ~) Y* K2 f1 q
global $elements, $stack, $depth;  
: f: ^* [: q0 U3 w5 g, hwww.520diannao.com
2 d# X- Y6 v9 c" o7 s  z- h  Qwww.520diannao.com// 增加目前元素的字符数目
/ A$ z- ^7 ^, c" L0 g8 f; ]我爱电脑技术社区--打造最好的电脑技术自学交流平台$elements[$stack][count($stack)-1]]->chars += strlen(trim($data));  
) u. B9 c: Y5 b) j3 lwww.520diannao.com}  我爱电脑技术论坛1 r- a0 e/ h8 W& W3 D8 E& V2 r

3 @+ ~1 @* U9 @: X9 ~- M3 W打造最好的电脑自学交流论坛// 产生解析器的实例
/ v+ U/ R/ S2 ]( g6 P( y打造最好的电脑自学交流论坛$parser = xml_parser_create();  
7 n& F8 K6 c) @打造最好的电脑自学交流论坛
* D1 P- T& b% f. Z// 设置处理函数
7 w5 P$ K! p% o8 D$ B3 ^打造最好的电脑自学交流论坛xml_set_element_handler($parser, "start_element", "stop_element");  
- \9 c; A- @0 P打造最好的电脑自学交流论坛xml_set_character_data_handler($parser, "char_data");  
3 k' g' O; g) n打造最好的电脑自学交流论坛xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);  www.520diannao.com+ C1 C( u! m* {: [; [9 i% T4 w

' H% @' \6 k+ \- Z) Y4 T// 解析文件 打造最好的电脑自学交流论坛, O8 u( S6 f1 _8 [6 V! U2 C
$ret = xml_parse_from_file($parser, $file);  
" O* F: ~" l; w$ W( ]& k4 H我爱电脑技术论坛if(!$ret)  
  q+ z/ s$ t4 @4 S{  打造最好的电脑自学交流论坛2 ?- G4 N9 n: I" c) C% G  r2 W
die(sprintf("XML error: %s at line %d",  
0 ^, e/ ?2 @& q! v/ S我爱电脑技术社区--打造最好的电脑技术自学交流平台xml_error_string(xml_get_error_code($parser)),  打造最好的电脑自学交流论坛3 Q# A: @2 a: \" _
xml_get_current_line_number($parser)));  打造最好的电脑自学交流论坛, Q9 e" V; ]' Z2 J
}  
% h9 P3 q0 s: S, Y8 v我爱电脑技术论坛
0 y% D4 A! e7 l0 C# ?0 y" i电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站// 释放解析器
9 H  l. W' b- `5 w我爱电脑技术论坛xml_parser_free($parser);  
' _: |  C5 |8 K* U我爱电脑技术社区--打造最好的电脑技术自学交流平台
( d; H; r1 r4 }, i- U" I" l7 [3 N我爱电脑技术论坛// 释放协助元素 电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站$ n, D* S4 b0 O) O, `9 I
unset($elements["current_element"]);  打造最好的电脑自学交流论坛' V3 [3 L+ z! l6 V2 n
unset($elements["last_element"]);  
5 t8 n% }! I+ q电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站
& ]! j7 V5 \0 Q5 e9 r, b我爱电脑技术社区--打造最好的电脑技术自学交流平台// 根据元素的次数排序
& v. A; i* _) }2 y! K2 C) }, K4 Dwww.520diannao.comuasort($elements, "my_sort");  $ b/ O- k0 L6 f$ |

2 T% Y- M( y9 Z. Kwww.520diannao.com// 在$elements中循环收集元素信息
% \: i% ^' g! `3 D3 lwww.520diannao.comwhile(list($name, $element) = each($elements))  * m" E, L- U  W( a8 \$ ?
{  我爱电脑技术论坛5 s0 Q+ Q3 F- \& f4 T' C- [: N# c9 B
print_box("Element name", $name);  
* _  P, A  X' V电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站- \, U! f6 _+ D+ J- a5 l1 r; b
print_line("Element count", $element->count);  我爱电脑技术社区--打造最好的电脑技术自学交流平台( l1 {& k* e& W: ^% M8 Q& b
print_line("Character count", $element->chars);  
* F/ ]. M# @1 x- [2 ]: Q7 p4 d我爱电脑技术社区--打造最好的电脑技术自学交流平台打造最好的电脑自学交流论坛: n9 s2 a" G! m0 j+ K- X7 O
printf("n%20sn", "* Parent elements");

TOP

// 在该元素的父中循环,输出结果 www.520diannao.com" O( f( K! |! T1 h& h& M3 q- W) W
while(list($key, $value) = each($element->parents))  打造最好的电脑自学交流论坛; Q. z$ V  s3 ^6 C3 Z: I1 z4 O
{  我爱电脑技术社区--打造最好的电脑技术自学交流平台* a; ], f" Y' o7 U$ ^! T
print_line($key, $value);  电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站5 ~6 r+ h6 O" f' h
}  我爱电脑技术论坛* r, W5 w7 V. A* s/ {+ ^
if(count($element->parents) == 0)  
6 u* c8 c1 Z% y) U! m" V我爱电脑技术社区--打造最好的电脑技术自学交流平台{  
2 N0 \' G( w/ w" fwww.520diannao.comprintf("%35sn", "[root element]");  
) Z- V. ~# T6 C/ k2 j8 z; w}  我爱电脑技术论坛" V4 _; G0 j! L9 V0 _  s% x
www.520diannao.com" R) V; q/ p1 }, g& h; i
// 在该元素的子中循环,输出结果 电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站1 [4 K, z# A/ ?- J& ~" v7 R8 ?( V
printf("n%20sn", "* Child elements");  
/ j! z4 u4 V) Y) [. t* Vwww.520diannao.comwhile(list($key, $value) = each($element->childs))  电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站- ?7 a, j- M6 R2 s1 @3 @
{  
- {! }6 z! A9 j$ ]4 z1 L/ b我爱电脑技术论坛print_line($key, $value);  
5 Q0 o, z4 }/ G% {& Q9 x4 t打造最好的电脑自学交流论坛}  " \1 B1 p2 K/ t8 ~/ Z
if(count($element->childs) == 0)  电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站5 {1 o: y# R6 C, K% r
{  电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站( r1 }0 `# i4 V& Y
printf("%35sn", "[no childs]");  我爱电脑技术社区--打造最好的电脑技术自学交流平台6 G' X1 T, N3 t4 F. Y$ L
}  打造最好的电脑自学交流论坛- A8 Z" N4 P1 ~+ `
www.520diannao.com# |: ?( Y, n! G; d$ s6 @: b. z' j
$total_elements += $element->count;  
3 ?- L% h$ @( J' N8 h" L& g我爱电脑技术论坛$total_chars += $element->chars;  
0 V, b& W5 v+ n( u2 D5 y/ N! W我爱电脑技术社区--打造最好的电脑技术自学交流平台}  电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站( d0 g7 i& V2 N3 ?4 W* X

8 u8 i7 q" c0 I5 X) Q我爱电脑技术社区--打造最好的电脑技术自学交流平台// 最终结果
2 h0 p! g" q8 O6 c我爱电脑技术社区--打造最好的电脑技术自学交流平台print_box("Total elements", $total_elements);  
: X6 R- {2 H! P5 i5 |打造最好的电脑自学交流论坛print_box("Total characters", $total_chars);  
/ y  @' |( }2 {7 |我爱电脑技术论坛?>

TOP

发新话题