Object Serialization: Object to Xml and Back

Coding Critique is the place to post source code for peer review by other members of DevNetwork. Any kind of code can be posted. Code posted does not have to be limited to PHP. All members are invited to contribute constructive criticism with the goal of improving the code. Posted code should include some background information about it and what areas you specifically would like help with.

Popular code excerpts may be moved to "Code Snippets" by the moderators.

Moderator: General Moderators

Post Reply
User avatar
yacahuma
Forum Regular
Posts: 870
Joined: Sun Jul 01, 2007 7:11 am

Object Serialization: Object to Xml and Back

Post 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);
koen.h
Forum Contributor
Posts: 268
Joined: Sat May 03, 2008 8:43 am

Re: Object Serialization: Object to Xml and Back

Post 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
User avatar
yacahuma
Forum Regular
Posts: 870
Joined: Sun Jul 01, 2007 7:11 am

Re: Object Serialization: Object to Xml and Back

Post 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.
Post Reply