Discuz教程网

PHP用SAX解析XML的实现代码与问题分析

[复制链接]
authicon dly 发表于 2011-8-31 10:53:10 | 显示全部楼层 |阅读模式
代码如下:

  1. <?php
  2. $g_books = array();
  3. $g_elem = null;
  4. function startElement( $parser, $name, $attrs )
  5. {
  6. global $g_books, $g_elem;
  7. if ( $name == 'BOOK' ) $g_books []= array();
  8. $g_elem = $name;
  9. }
  10. function endElement( $parser, $name )
  11. {
  12. global $g_elem;
  13. $g_elem = null;
  14. }
  15. function textData( $parser, $text )
  16. {
  17. global $g_books, $g_elem;
  18. if ( $g_elem == 'AUTHOR' ||
  19. $g_elem == 'PUBLISHER' ||
  20. $g_elem == 'TITLE' )
  21. {
  22. $g_books[ count( $g_books ) - 1 ][ $g_elem ] = $text;
  23. }
  24. }
  25. $parser = xml_parser_create();
  26. xml_set_element_handler( $parser, "startElement", "endElement" );
  27. xml_set_character_data_handler( $parser, "textData" );
  28. $f = fopen( 'books.xml', 'r' );
  29. while( $data = fread( $f, 4096 ) )
  30. {
  31. xml_parse( $parser, $data );
  32. }
  33. xml_parser_free( $parser );
  34. foreach( $g_books as $book )
  35. {
  36. echo $book['TITLE']." - ".$book['AUTHOR']." - ";
  37. echo $book['PUBLISHER']."\n";
  38. }
  39. ?>
复制代码




PHP中用SAX方式解析XML发现的问题
XML如下:
so.xml
代码如下:

  1. <?xml version="1.0" encoding="GBK"?>
  2. <result>
  3. <row>
  4. <id>1047869</id>
  5. <date>2008-08-28 14:54:51</date>
  6. <title>红花还需绿叶扶--浅谈脚架云台的选购</title>
  7. <summary>很多专业摄影师在选购三脚架的时候,往往出手阔绰,3、4000元一个的捷信或者曼富图三脚架常常不用经过思考就买下来了,可是,他们却总是忽视了云台的精挑细眩其实,数码相机架在三脚架上面究竟稳不稳,起决定作用的是云台,那么我们如何才能挑选到一款稳如磐石的云台呢?云台家族种类繁多用途迥异简单的说,脚架云台是用于连接相机与脚架进行角度调节的部件,主要分成三维云台和球型云台。三维云台在横向旋转</summary>
  8. </row>
  9. ...(省略若干行)
  10. </result>
复制代码




xml_class.php
代码如下:

  1. <?php
  2. class xml {
  3. var $parser;
  4. var $i =0;
  5. var $search_result = array();
  6. var $row = array();
  7. var $data = array();
  8. var $now_tag;
  9. var $tags = array("ID", "CLASSID", "SUBCLASSID", "CLASSNAME", "TITLE", "SHORTTITLE", "AUTHOR", "PRODUCER", "SUMMARY", "CONTENT", "DATE");
  10. function xml()
  11. {
  12. $this->parser = xml_parser_create();
  13. xml_set_object($this->parser, $this);
  14. xml_set_element_handler($this->parser, "tag_open", "tag_close");
  15. xml_set_character_data_handler($this->parser, "cdata");
  16. }
  17. function parse($data)
  18. {
  19. xml_parse($this->parser, $data);
  20. }
  21. function tag_open($parser, $tag, $attributes)
  22. {
  23. $this->now_tag=$tag;
  24. if($tag=='RESULT') {
  25. $this->search_result = $attributes;
  26. }
  27. if($tag=='ROW') {
  28. $this->row[$this->i] = $attributes;
  29. }
  30. }
  31. function cdata($parser, $cdata)
  32. {
  33. if(in_array($this->now_tag, $this->tags)){
  34. $tagname = strtolower($this->now_tag);
  35. $this->data[$this->i][$tagname] = $cdata;
  36. }
  37. }
  38. function tag_close($parser, $tag)
  39. {
  40. $this->now_tag="";
  41. if($tag=='ROW') {
  42. $this->i++;
  43. }
  44. }
  45. }
  46. ?>
复制代码




search.php
代码如下:

  1. <?php
  2. require_once("./xml_class.php");
  3. $xml = file_get_contents("./so.xml");
  4. $xml_parser = new xml();
  5. $xml_parser->parse($xml);
  6. print_r($xml_parser);
  7. ?>
复制代码

最后得到的结果中summary中的数据少了很多,总是得不到完整的summary内容。有时还会得到乱码,在网上也找了半天也不知道是什么问题引起的。
  后来才发现问题是因为xml_parser解析XML是循环处理节点中的数据的,每次只取大概300个字符长度(具体是多少,我也不太清楚,只是用strlen输出大概在300左右),于是才知道是因为每次的循环就会把前次的数据给复盖了,这样就会出现数据不全的问题。
  解决办法就是把xml_class文件中的xml类中的cdata方法中$this->data[$this->i][$tagname] = $cdata;改为$this->data[$this->i][$tagname] .= $cdata;即可解决(其中有一些NOTICE错误,PHP已忽略了).






上一篇:PHP数组实例总结与说明
下一篇:PHP表单验证的3个函数ISSET()、empty()、is_numeric()的使用方法
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

1314学习网 ( 浙ICP备10214163号 )

GMT+8, 2025-5-2 18:18

Powered by Discuz! X3.4

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表