+ -
当前位置:首页 → 问答吧 → 自己写的xml解析函数,效率不错...

自己写的xml解析函数,效率不错...

时间:2008-09-21

来源:互联网

自己写的XML解析函数,功能比较少,只支持普通的XML格式、CDATA、属性单双引号.....
其实写来主要是配合缓存模块的,对于功能要求不大.....
经过三台服务器测试,WINDOWS和LINUX下运行良好......
以下测试文档,平均耗时:0.0007 毫秒(汗...打少一个0了)

测试的XML文档:
[php]
<?xml version='1.0' encoding='UTF-8'?>
<root>
        <key id="5201314" name="望咩掉啊">
                <user id='6789' name='不上学了'><![CDATA[我靠!!!@*&^$(*%&]]></key>
                <user id="6789" name="不上学了">222</key>
        </key>
        <key id="5201314" name="望咩掉啊">
                <user id='6789' name='不上学了'><![CDATA[我靠!!!|""!@":#$@$]]></key>
                <user id="6789" name="不上学了">222</key>
        </key>
        <key id="5201314" name="望咩掉啊">
                <user id='6789' name='不上学了'><![CDATA[我靠!!!<><><><>]]></key>
                <user id="6789" name="不上学了">222</key>
        </key>
</root>
[/php]
[php]
<?php
/*  func.xml.php  2008-09-20  kilobug
必须声明头部属性,xml每个节点的值和属性严禁出现 <、>、" 字符,如需出现,请使用CDATA
每个节点属性必须统一使用单引号'或双引号"
忽略注释,返回一个数组。
*/

$xmlContent = ''; //临时变量

/* 载入xml文件,解析后返回数组 */
function loadXML( $path, $assoc = null, $attrassoc = null ) {
return parseXML( @file_get_contents( $path ), $assoc, $attrassoc );
}
/* 解析XMl内容,返回数组 */
function parseXML( $xmltext, $assoc = null, $attrassoc = null ) {
$xmldata = array();
//转换顶部属性
$noderoot = strpos( $xmltext, '<?' );
$noderootspace = strpos( $xmltext, ' ' );
$nodefoot = strpos( $xmltext, '?>' );
$attr = trim( substr($xmltext, $noderootspace, $nodefoot-$noderoot-5) );
//转换节点
$xmldata = array_merge(
   array(
    array_merge(
     array( substr($xmltext, $noderoot+2, $noderootspace-$noderoot-2) ),
     parseXMLAttrs($attr, $attrassoc)
    )
   ),
   parseXMLNodes( trim(substr($xmltext, $nodefoot+2)), $assoc, $attrassoc )
     );
return $xmldata;
}
/* 解析XML节点,返回数组 */
function parseXMLNodes( $nodestr, $assoc = null, $attrassoc = null ) {
global $xmlContent;
$xmlContent = $nodestr;
if ( empty($xmlContent) || !strstr($xmlContent, '<') ) {
  return array();
}
$nodedate = array();
$i = 0;
while ( !empty($xmlContent) ) {
  $noderoot = strpos( $xmlContent, '<' );
  $nodefoot = strpos( $xmlContent, '>' );
  $nodeend = strpos( $xmlContent, '/' );
  $cdataroot = strpos( $xmlContent, '<![CDATA[' );
  $cdatafoot = strpos( $xmlContent, ']]>' );
  if ( $noderoot === $cdataroot ) { //判断是否CDATA
   $nodedate = substr($xmlContent, $cdataroot+9, $cdatafoot-$cdataroot-9);
   $xmlContent = substr( $xmlContent, strpos($xmlContent, '>', $cdatafoot+3)+1 );
   break $nodedate;
  } else if ( $noderoot == $nodeend-1 ) { //是否结束节点,是则返回前面的内容
   if ( $i == 0 ) {
    $nodedate = substr( $xmlContent, 0, $noderoot );
    $xmlContent = substr( $xmlContent, $nodefoot+1 );
    return $nodedate;
   }
   else {
    $xmlContent = substr( $xmlContent, $nodefoot+1 );
    break;
   }
  }
  $nodecompart = strpos( $xmlContent, ' ' );
  //判断有无属性
  if ( $nodecompart != false && $nodecompart > $noderoot && $nodecompart < $nodefoot ) { //有属性
   $nodedate[$i][0] = array_merge( array($assoc ? substr($xmlContent, $noderoot+1, $nodecompart-$noderoot-1) : ''), parseXMLAttrs(substr($xmlContent, $nodecompart+1, $nodefoot-$nodecompart-($nodefoot-1 == $nodeend ? 2 : 1)), $attrassoc) );
   
  } else { //无属性
   $nodedate[$i][0] = array( $assoc ? substr($xmlContent, $noderoot+1, $nodefoot-$noderoot-1) : '' );
  }
  $i++;
  $xmlContent = substr( $xmlContent, $nodefoot+1 ); //截取本节点后面内容
  if ( $nodefoot-1 == $nodeend ) { //判断是否单节点
   $nodedate[$i-1][1] = '';
   continue;
  } else {
   $nodedate[$i-1][1] = parseXMLNodes( $xmlContent, $assoc, $attrassoc );
  }
}
return $nodedate;
}
/* 解析XML节点属性,返回数组 */
function parseXMLAttrs( $attrstr, $assoc = null ) {
if ( !$attrstr ) return array();
echo( $attrstr . "\n" );
$attrdata = array();
$attrcenter = $attrfoot = 1; //开始转换
$tmpnum = false;
while ( $attrcenter != false ) {
  $tmpnum = strpos($attrstr, '=\'');
  $attrcenter = strpos($attrstr, '="');
  if ( $tmpnum == false ) {
   $attrfoot = strpos($attrstr, '"', $attrcenter+2);
  } else {
   $attrcenter = $tmpnum;
   $attrfoot = strpos($attrstr, '\'', $attrcenter+2);
  }
  if ( $assoc ) { //是否关联数组
   $attrdata[substr( $attrstr, 0, $attrcenter)] = substr( $attrstr, $attrcenter+2, $attrfoot-$attrcenter-2 );
  } else {
   $attrdata[] = substr( $attrstr, $attrcenter+2, $attrfoot-$attrcenter-2 );
  }
  $attrstr = trim(substr($attrstr, $attrfoot+1));
  if ( !$attrstr ) {
   break;
  }
}
return $attrdata;
}

//解析数组为XML(没写)
function parseArrayToXML( $ary ) {
        
}
//解析数组为XML的Nodes(没写)
function parseArrayToXMLNodes( $ary ) {
        
}

/* 测试
$t = microtime();
//loadXML('../books.xml');
print_r( loadXML('../test.xml', 1, 1) ); //自己找一个常见的xml文档
echo microtime() - $t;
*/

?>
[/php]

作者: kilobug   发布时间: 2008-09-21

...没人顶?

作者: adriandcb   发布时间: 2008-10-09

作者: kupe   发布时间: 2008-10-10

可以看看magpierss

作者: omcmc   发布时间: 2008-10-10

看看。

作者: sueswriter   发布时间: 2008-10-10

顶一个!!!

作者: 海底人   发布时间: 2008-10-10

楼主我顶你~~~
终于找到个XML解析函数啦~~~谢谢

作者: jeftom   发布时间: 2008-10-29

在PHPCMS中有一个这样的,偶拿出来用的时候却报错说是“未定义索引”。

[code]function xml_file($filename, $keyid = 'errorlog')
{
$string = implode('', file($filename));
return xml_str($string, $keyid);
}

function xml_str($string, $keyid = 'errorlog')
{
$parser = xml_parser_create();
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
xml_parse_into_struct($parser, $string, $values, $tags);
xml_parser_free($parser);
$tdb = array();

foreach ($tags as $key=>$val)
{
if($key != $keyid) continue;
$molranges = $val;
for ($i=0; $i < count($molranges); $i+=2)
{
$offset = $molranges[$i] + 1;
$len = $molranges[$i + 1] - $offset;
$tdb[] = xml_arr(array_slice($values, $offset, $len));
}
}
return $tdb;
}

function xml_arr($mvalues)
{
$arr = array();
for($i=0; $i < count($mvalues); $i++)
{
$arr[$mvalues[$i]['tag']] = $mvalues[$i]['value'];
}
return $arr;
}[/code]

作者: jeftom   发布时间: 2008-10-29