<?php
//XML2Json 主程式, XML2JsonSub 遞迴需要用的子程式, Xml2Array - 由 php.net 抓來的 Xml Parse(此 class 可 parse 出 tag 中的屬性)
/*
// example:
$rss = file_get_contents('rss.xml');
$json = Xml2Json($rss);
echo $json;
*/

function Xml2Json($xml_data)
{
    
$xml = new xml2Array();
    
$xml_ary $xml->parse($xml_data);

    
$json '';
    for(
$i=0$c=count($xml_ary); $i $c$i++) {
        
$xml_ary[$i]['name'] = addslashes($xml_ary[$i]['name']);
        
$json .= "\"{$xml_ary[$i]['name']}\":{" rtrimtrim(Xml2JsonSub($xml_ary[$i]['children'])), ',' ) . "}\n";
        
$json rtrim($json',');
    }

    return 
$json;
}

function 
Xml2JsonSub($xml_ary)
{
    
$json '';
    for(
$i=0$c=count($xml_ary); $i $c$i++) {
        if ( 
is_array$xml_ary[$i]['attrs'] ) && count($xml_ary[$i]['attrs']) > ) {
            foreach( 
$xml_ary[$i]['attrs'] as $attr_key => $attr ) {
                
$json .= "\"@$attr_key\":\"$attr\",";
            }
            
$json .= ( empty($xml_ary[$i]['tagData']) ) ? '' "\"#{$xml_ary[$i]['tagData']}\":\"".$xml_ary[$i]['tagData'].'",';
        } else {
            if ( isset(
$xml_ary[$i]['children']) ) {
                
$xml_ary[$i]['name'] = addslashes($xml_ary[$i]['name']);
                
$xml_ary[$i]['tagData'] = addslashes($xml_ary[$i]['tagData']);
                
$json .= "\"{$xml_ary[$i]['name']}\":{" rtrim(trim(Xml2JsonSub($xml_ary[$i]['children'])),',') . ",";

                if( empty(
$xml_ary[$i]['tagData']) ) {
                    
$json .= '"'$xml_ary[$i]['name'] .'":null,';
                } else {
                    
$json .= '"'$xml_ary[$i]['name'] .'":"'$xml_ary[$i]['tagData'] . '",';
                }

                
$json rtrim($json',');
                
$json .= '},';
            } else {
                
$xml_ary[$i]['name'] = addslashes($xml_ary[$i]['name']);
                
$xml_ary[$i]['tagData'] = addslashes($xml_ary[$i]['tagData']);

                
$json .= '{';
                if( empty(
$xml_ary[$i]['tagData']) ) {
                    
$json .= '"'$xml_ary[$i]['name'] .'":null,';
                } else {
                    
$json .= '"'$xml_ary[$i]['name'] .'":"'$xml_ary[$i]['tagData'] . '",';
                }

                
$json rtrim($json',');
                
$json .= '},';
            }
        }
    }
    return 
$json;
}

class 
xml2Array {
    var 
$arrOutput = array();
    var 
$resParser;
    var 
$strXmlData;

    function 
parse($strInputXML) {

        
$this->resParser xml_parser_create ();
        
xml_set_object($this->resParser,$this);
        
xml_set_element_handler($this->resParser"tagOpen""tagClosed");

        
xml_set_character_data_handler($this->resParser"tagData");

        
$this->strXmlData xml_parse($this->resParser,$strInputXML );
        if(!
$this->strXmlData) {
            die(
sprintf("XML error: %s at line %d",
                        
xml_error_string(xml_get_error_code($this->resParser)),
                        
xml_get_current_line_number($this->resParser)));
        }

        
xml_parser_free($this->resParser);

        return 
$this->arrOutput;
    }
    function 
tagOpen($parser$name$attrs) {
        
$tag=array("name"=>$name,"attrs"=>$attrs);
        
array_push($this->arrOutput,$tag);
    }

    function 
tagData($parser$tagData) {
        if(
trim($tagData)) {
            if(isset(
$this->arrOutput[count($this->arrOutput)-1]['tagData'])) {
                
$this->arrOutput[count($this->arrOutput)-1]['tagData'] .= $tagData;
            }
            else {
                
$this->arrOutput[count($this->arrOutput)-1]['tagData'] = $tagData;
            }
        }
    }

    function 
tagClosed($parser$name) {
        
$this->arrOutput[count($this->arrOutput)-2]['children'][] = $this->arrOutput[count($this->arrOutput)-1];
        
array_pop($this->arrOutput);
    }
}
?>