Alex Rivera | Logout

PHP Object as XML Document

Asked 2008-09-26T00:05:11.973
51

What is the best way to take a given PHP object and serialize it as XML? I am looking at simple_xml and I have used it to parse XML into objects, but it isn't clear to me how it works the other way around.

Edit
Report

2 Answers

3

take a look at my version

    class XMLSerializer {

    /**
     * 
     * The most advanced method of serialization.
     * 
     * @param mixed $obj => can be an objectm, an array or string. may contain unlimited number of subobjects and subarrays
     * @param string $wrapper => main wrapper for the xml
     * @param array (key=>value) $replacements => an array with variable and object name replacements
     * @param boolean $add_header => whether to add header to the xml string
     * @param array (key=>value) $header_params => array with additional xml tag params
     * @param string $node_name => tag name in case of numeric array key
     */
    public static function generateValidXmlFromMixiedObj($obj, $wrapper = null, $replacements=array(), $add_header = true, $header_params=array(), $node_name = 'node') 
    {
        $xml = '';
        if($add_header)
            $xml .= self::generateHeader($header_params);
        if($wrapper!=null) $xml .= '<' . $wrapper . '>';
        if(is_object($obj))
        {
            $node_block = strtolower(get_class($obj));
            if(isset($replacements[$node_block])) $node_block = $replacements[$node_block];
            $xml .= '<' . $node_block . '>';
            $vars = get_object_vars($obj);
            if(!empty($vars))
            {
                foreach($vars as $var_id => $var)
                {
                    if(isset($replacements[$var_id])) $var_id = $replacements[$var_id];
                    $xml .= '<' . $var_id . '>';
                    $xml .= self::generateValidXmlFromMixiedObj($var, null, $replacements,  false, null, $node_name);
                    $xml .= '</' . $var_id . '>';
                }
            }
            $xml .= '</' . $node_block . '>';
        }
        else if(is_array($obj))
        {
            foreach($obj as $var_id => $var)
            {
                if(!is_object($var))
               
answered 2013-04-04T13:33:30.940
-1

While I agree with @philfreo and his reasoning that you shouldn't be dependant on PEAR, his solution is still not quite there. There are potential issues when the key could be a string that contains any of the following characters:

  • <
  • >
  • \s (space)
  • "
  • '

Any of these will throw off the format, as XML uses these characters in its grammar. So, without further ado, here is a simple solution to that very possible occurrence:

function xml_encode( $var, $indent = false, $i = 0 ) {
    $version = "1.0";
    if ( !$i ) {
        $data = '<?xml version="1.0"?>' . ( $indent ? "\r\n" : '' )
                . '<root vartype="' . gettype( $var ) . '" xml_encode_version="'. $version . '">' . ( $indent ? "\r\n" : '' );
    }
    else {
        $data = '';
    }

    foreach ( $var as $k => $v ) {
        $data .= ( $indent ? str_repeat( "\t", $i ) : '' ) . '<var vartype="' .gettype( $v ) . '" varname="' . htmlentities( $k ) . '"';

        if($v == "") {
            $data .= ' />';
        }
        else {
            $data .= '>';
            if ( is_array( $v ) ) {
                $data .= ( $indent ? "\r\n" : '' ) . xml_encode( $v, $indent, $verbose, ($i + 1) ) . ( $indent ? str_repeat("\t", $i) : '' );
            }
            else if( is_object( $v ) ) {
                $data .= ( $indent ? "\r\n" : '' ) . xml_encode( json_decode( json_encode( $v ), true ), $indent, $verbose, ($i + 1)) . ($indent ? str_repeat("\t", $i) : '');
            }
            else {
                $data .= htmlentities( $v );
            }

            $data .= '</var>';
        }

        $data .= ($indent ? "\r\n" : '');
    }

    if ( !$i ) {
        $data .= '</root>';
    }

    return $data;
}

Here is a sample usage:

// sample object
$tests = Array(
    "stringitem" => "stringvalue",
    "integeritem" => 1,
    "floatitem" => 1.00
answered 2011-07-26T23:59:32.033

Your Answer