ThinkPHP XML格式转换成数组

jerry thinkphp 2015年11月18日 收藏
XML格式转换成数组 用递归操作很简单,大家可以下载附件测试
// Xml 转 数组, 包括根键,忽略空元素和属性,尚有重大错误
public function xml_to_array( $xml )
    {
        $reg = "/<(\\w+)[^>]*?>([\\x00-\\xFF]*?)<\\/\\1>/";
        if(preg_match_all($reg, $xml, $matches))
        {
            $count = count($matches[0]);
            $arr = array();
            for($i = 0; $i < $count; $i++)
            {
                $key = $matches[1][$i];
                $val = $this->xml_to_array( $matches[2][$i] );  // 递归
                if(array_key_exists($key, $arr))
                {
                    if(is_array($arr[$key]))
                    {
                        if(!array_key_exists(0,$arr[$key])) 
                        {
                            $arr[$key] = array($arr[$key]);
                        }
                    }else{
                        $arr[$key] = array($arr[$key]);
                    }
                    $arr[$key][] = $val;
                }else{
                    $arr[$key] = $val;
                }
            }
            return $arr;
        }else{
            return $xml;
        }
    }


// Xml 转 数组, 不包括根键
public function xmltoarray( $xml )
    {

        $arr = $this->xml_to_array($xml);
        $key = array_keys($arr);
        return $arr[$key[0]];
    }
第二种方法,预防递归溢出
class XML
{

public $parser = NULL;
public $document = NULL;
public $parent = NULL;
public $stack = NULL;
public $last_opened_tag = NULL;

public function XML( )
    {
        $this->parser = xml_parser_create( );
        xml_parser_set_option( $this->parser, XML_OPTION_CASE_FOLDING, false );
        xml_set_object( $this->parser, $this );
        xml_set_element_handler( $this->parser, "open", "close" );
        xml_set_character_data_handler( $this->parser, "data" );
    }

public function destruct( )
    {
        xml_parser_free( $this->parser );
    }

public function &parse( &$data )
    {
        $this->document = array( );
        $this->stack = array( );
        $this->parent =& $this->document;
        $parsedata = xml_parse( $this->parser, $data, true ) ? $this->document : NULL;
        return $parsedata;
    }

public function open( &$parser, $tag, $attributes )
    {
        $this->data = "";
        $this->last_opened_tag = $tag;
        if ( is_array( $this->parent ) && array_key_exists( $tag, $this->parent ) )
        {
            if ( is_array( $this->parent[$tag] ) && array_key_exists( 0, $this->parent[$tag] ) )
            {
                $key = count_numeric_items( $this->parent[$tag] );
            }
            else
            {
                if ( array_key_exists( "{$tag} attr", $this->parent ) )
                {
                    $arr = array(
                        "0 attr" => $this->parent["{$tag} attr"],
                        $this->parent[$tag]
                    );
                    unset( $this->parent["{$tag} attr"] );
                }
                else
                {
                    $arr = array(
                        $this->parent[$tag]
                    );
                }
                $this->parent[$tag] =& $arr;
                $key = 1;
            }
            $this->parent =& $this->parent[$tag];
        }
        else
        {
            $key = $tag;
        }
        if ( $attributes )
        {
            $this->parent["{$key} attr"] = $attributes;
        }
        $this->parent =& $this->parent[$key];
        $this->stack[] =& $this->parent;
    }

public function data( &$parser, $data )
    {
        if ( $this->last_opened_tag != NULL )
        {
            $this->data .= $data;
        }
    }

public function close( &$parser, $tag )
    {
        if ( $this->last_opened_tag == $tag )
        {
            $this->parent = $this->data;
            $this->last_opened_tag = NULL;
        }
        array_pop( $this->stack );
        if ( $this->stack )
        {
            $this->parent =& $this->stack[count( $this->stack ) - 1];
        }
    }

}

function &XML_unserialize( &$xml )
{
    $xml_parser = new XML( );
    $data =& $xml_parser->parse( $xml );
    $xml_parser->destruct( );
    return $data;
}

function &XML_serialize( &$data, $level = 0, $prior_key = NULL )
{
    if ( $level == 0 )
    {
        ob_start( );
        echo "<?xml version=\"1.0\" ?>";
        echo "\n";
    }
    while ( list( $key, $value ) = each( $data ) )
    {
        if ( !strpos( $key, " attr" ) )
        {
            if ( is_array( $value ) && array_key_exists( 0, $value ) )
            {
                xml_serialize( $value, $level, $key );
            }
            else
            {
                $tag = $prior_key ? $prior_key : $key;
                echo str_repeat( "\t", $level );
                echo "<";
                echo $tag;
                if ( array_key_exists( "{$key} attr", $data ) )
                {
                    while ( list( $attr_name, $attr_value ) = each( $data["{$key} attr"] ) )
                    {
                        echo " ";
                        echo $attr_name;
                        echo "=\"";
                        echo htmlspecialchars( $attr_value );
                        echo "\"";
                    }
                    reset( $data["{$key} attr"] );
                }
                if ( is_null( $value ) )
                {
                    echo " />\n";
                }
                else if ( !is_array( $value ) )
                {
                    echo ">";
                    echo htmlspecialchars( $value );
                    echo "</{$tag}>\n";
                }
                else
                {
                    echo ">\n";
                    echo xml_serialize( $value, $level + 1 );
                    echo str_repeat( "\t", $level );
                    echo "</{$tag}>\n";
                }
            }
        }
    }
    reset( $data );
    if ( $level == 0 )
    {
        $str =& ob_get_contents( );
        ob_end_clean( );
        return $str;
    }
}

function count_numeric_items( &$array )
{
    return is_array( $array ) ? count( array_filter( array_keys( $array ), "is_numeric" ) ) : 0;
}

附件IndexModel.class.zip ( 705 B 下载:75 次 )