Page 1 of 1

Object Serialization: Object to Xml and Back

Posted: Thu May 05, 2011 1:22 pm
by yacahuma
Hello, I needed a way to create a clean xml of an object and the read it back and get my original object. I search and all I found was xml to array stuff. And the ones that advertise and object was never the correct (original class). I made the following code and seem to work for all the test I created (not many). I would like your opinions and comments if it can be improved.

Thank you

Code: Select all

    class XmlSerializer
    {

        function xmlTag($t, $v)
        {
            $nv =  str_replace( array('&','"',"'",'<','>'),
            array('&','"','&apos;','<','>'), trim($v));
            
            return "<$t>" . $nv. "</$t>";
        }

        function loadXml($xmlobj,&$obj)
        {

            foreach(array_keys(get_object_vars($xmlobj)) as $k)
            {
                if ($k=='@attributes')
                {
                    $objtype = (string) $xmlobj->attributes()->is_a;
                    if(is_null($obj))    //i dont always want to create a new alement, ex, passing $this
                      $obj = new $objtype;
                }
                else if (count($xmlobj->$k->attributes()) == 0) //FINAL VARIABLE
                    {
                        $obj->$k = (string) $xmlobj->$k;
                    }
                    else
                    {
                        $is_a = (string) $xmlobj->$k->attributes()->is_a; 
                        if ($is_a == 'Array')
                        {
                            $arrayName = (array_keys(get_object_vars($xmlobj->$k)));
                            foreach($xmlobj->$k->$arrayName[1] as $node)
                            {
                                $tmp = null;
                                XmlSerializer::loadXml($node,$tmp); 
                                array_push($obj->$k, $tmp);
                            }
                        } 
                        else 
                            XmlSerializer::loadXml($xmlobj->$k,$obj->$k); //IS AN OBJECT
                }
            }


        }//loadXml  

        function getXml($obj,$show=1)
        {
            $cn = get_class($obj);
            $xml='';
            if ($show==1)
                $xml .= '<' . $cn . ' is_a="'.$cn.'">'; 
            foreach(array_keys(get_class_vars(get_class($obj))) as $k)
            {
                if (is_array($obj->$k))
                {
                    $xml .= '<' . $k . ' is_a="Array">'; 
                    foreach($obj->$k as $arrobj)
                        $xml .= XmlSerializer::getXml($arrobj,1); //send the obj only
                    $xml .= '</' . $k . '>'; 
                }
                else if (is_object($obj->$k))
                        $xml .= '<' . $k . ' is_a="'.get_class($obj->$k).'">' . XmlSerializer::getXml($obj->$k,0) . '</' . $k . '>'; 

                    else 
                        $xml .= XmlSerializer::xmlTag($k,$obj->$k);

            } 
            if ($show==1)      
                $xml .= "</{$cn}>";
            return $xml;
        }
    }

    //HOW TO USE
    // $xml = XmlSerializer::getXml($obj);


    // $newobj = null;
    // XmlSerializer::loadXml(new SimpleXMLElement($xml),$newobj);

And to test it

Code: Select all

    class MyTest
    {
        var $var1;
        var $var2;
        var $var3isobj;
    }

    class Class1
    {
        //Part 1
        var $ThisIsAString1;
        var $ThisIsAString2;
        var $ThisIsAString3;
        var $ThisIsAString4;  
        var $ThisIsObj;
        var $ThisIsArray;

        function __construct()
        {
            $this->ThisIsArray = array();
            $this->ThisIsObj = new MyTest();

        }
    }

    $v =  new Class1();
    $v->ThisIsAString1=3;
    $v->ThisIsAString2=2;
    $v->ThisIsAString3=1;   
    $v->ThisIsObj->var1=88;
    $v->ThisIsObj->var2=92;

    $tmp1 = new MyTest();
    $tmp1->var1 = 890;
    $tmp1->var2 = 765;

    $tmp2 = new MyTest();
    $tmp2->var1 = 322;
    $tmp2->var2 = 111;
    $tmp2->var3isobj = new MyTest();
    $tmp2->var3isobj->var1 = 777;



    $v->ThisIsArray[] = $tmp1;
    $v->ThisIsArray[] = $tmp2;
   

    echo "<BR>THIS IS THE ORIGINAL OBJECT";
    print_r($v);


    $xml = XmlSerializer::getXml($v);
    echo htmlentities($xml);


    $d = new SimpleXMLElement($xml);

    $v2 = null;
    XmlSerializer::loadXml(new SimpleXMLElement($xml),$v2);

    echo '<HR>THIS IS THE FINAL OBJECT';
    print_r($v2);

Re: Object Serialization: Object to Xml and Back

Posted: Thu May 05, 2011 2:24 pm
by koen.h
This is probably not the kind of critique you are looking for BUT one of my pet peeves is 'intention revealing names'. I will make a bet with you that if this class is stored unused on your disk for one month you will have to read the code line by line to understand how it all worked.

$xmlSerializer->xmlTag($uhr... $t? wtf is $t what did I need to put in here? ok let's go through the code to find out

Re: Object Serialization: Object to Xml and Back

Posted: Thu May 05, 2011 7:18 pm
by yacahuma
well, the code is not that big. Are you saying I should use better variables names? Not a priority, but thank you. I am looking more in terms of performance or if there is a better way to do it.