Php 5 Serialization Xml into a class or Serialize Class to Xml

1,946 views
Skip to first unread message

webmouse

unread,
Apr 5, 2008, 7:47:17 PM4/5/08
to Professional PHP Developers
i have a problem in php 5 .As normally i'm a C# Developper but now i
want to write a library in php 5 with oop ..But i Have a problem so.
my problem is that
i want to serialize a Php 5 class to Xml with its datas....
or want to deserialize a xml file into a class ...
for example
i have a hede class

class hede
{
private $var1;
private $var2;
public function get_var1()
{}
public function get_var2()
{}
public function set_var1($Value)
{}
public function set_var2($Value)
{}

}


i have a class

and


$instance= new hede();
$instance -> set_var2(123);

and now i want to serialize this class into a xml file


<hede>
<var1 />
<var2>123</var2>
</hede>

thats the result...


and i want to deserialize this xml file into my instance .. after this
i must write this instance->get_var2(); and the result after this must
be 123

i want a serialize as .net ...

please help me with examle codes i neeed this... Thank you everybody .

naholyr

unread,
Apr 6, 2008, 9:04:11 AM4/6/08
to Professional PHP Developers
Do you *really* need XML ? Because otherwise you could simply use the
optimized PHP serialize().

Otherwise I think the simpliest way is to create functions that will
convert PHP-serialization strings from/to XML.
I propose you an organization, the hard work is still to be done : you
have to analyze the format of a PHP-serialize string, to be able to
convert it from/to XML :)

Why work from PHP-serialize ? Because a serialization must include all
the attributes, even if protected of private. Building the serialized
string is not the problem, as the Reflection API or (even simplier)
get_object_vars($this) will provide the values of every attribute
regardless of its visibility. The problem comes when you must rebuild
the object, if you can't call the built-in "unserialize()" you will
not be able to create a new object and set its private or protected
attributes. So you have no choice to unserialize, you *must* call
unserialize() so you *must* be able to build a valid string for this
function.



class Serialize
{

/**
* Serializes a variable
* @param mixed $object
* @return string strict string representation
*/
public static function serialize($object)
{
return serialize($object);
}

/**
* Unserializes a variable
* @param string $string
* @return mixed
*/
public static function unserialize($string)
{
return unserialize($string);
}

}



class XMLSerialize extends Serialize
{

/**
* Serializes a variable
* @param mixed $object
* @return string strict string representation
*/
public static function serialize($object)
{
$string = parent::serialize($object);
$xml = self::stringToXML($string);
return $xml;
}

/**
* Unserializes a variable
* @param string $string
* @return mixed
*/
public static function unserialize($xml)
{
$string = self::XMLToString($xml);
return parent::unserialize($string);
}

/**
* Converts a PHP-serialize string to an XML representation
* @param string $string
* @return string $xml
*/
protected static function stringToXML($string)
{
// ... have fun here ...
}

/**
* Converts an XML representation to a PHP-serialize string
* @param string $xml
* @return string $string
*/
protected static function XMLToString($string)
{
// ... have fun here ...
}

}



To give you some basic hints, here is the serialization format for
main types :

## String ##
s:$length:"$value";
$length is the string's length
$value is the direct (unescaped) string's value

## Integer ##
i:$value;

## Double ##
d:$value;
You will notice some bugs in the float-representation. Another
argument to use serialize() & unserialize() which will get through
those bugs. E.g. serialize(0.33) gives $s = "d:
0.330000000000000015543122344752191565930843353271484375;" and when
you echo unserialize($s) it will display 0.33. Don't ask me how this
works, floats are always crap in every systems anyway.

## Booleans ##
b:$value;
$value is 1 or 0

## NULL ##
N;

## Array ##
a:$length:$hashSerialization
$length is the length of the array
$hashSerialization is the serialization of the key/value pairs in the
array (see "hash serialization below")

## Object ##
O:$classNameLength:"$className":$nbAttributes:$attributesSerialization
$classNameLenght is the length of the className
$className is the className
$nbAttributes is the number of attributes
$attributesSerialization is the serialization of the attribute-name/
attribute-value pairs (see "hash serialization below"). The attribute-
name is built following this rule :
- public attribute : use directly the name
- protected attribute : prefix the name with a star "*"
- private attribute : prefix the name with chr(0) . $className .
chr(0)

## Hash serialization ###
{$pair1;$pair2;...$pairN;}
$pairX is the serialization of the Xth pair in the hash, its
representation is $key;$value, where :
$key is the serialization of the key
$value is the serialisation of the value

## Example ##

class MyClass {
private $privateAttr = "toto";
protected $protAttr = "titi";
public $var = "tata";
}

$v1 = new MyClass;
$v2 = 'a string";';
$v3 = 367;
echo serialize(array($v1, $v2, 'integer' => $v3));

Will display this string :
a:3:{i:0;O:7:"MyClass":3:{s:20:"MyClassprivateAttr";s:4:"toto";s:
11:"*protAttr";s:4:"titi";s:3:"var";s:4:"tata";}i:1;s:10:"a
string";";s:7:"integer";i:367;}

You will notice that no character is escaped when the string is
serialized, and you may think this would cause a corruption. No, there
is no such risk, because the length of the string is given in the
serialization : when the parser reads "s:10:" he just takes the 10
next characters and builds the string with those, without regarding
the characters.



Last advice : don't try to make a single regexp to parse serialized
string. You'd better build a usual parser (going forward character(s)
by character(s)).

naholyr

unread,
Apr 6, 2008, 9:08:07 AM4/6/08
to Professional PHP Developers
Hmmm, there is another possibility, which requires a custom install :
http://fr2.php.net/manual/fr/ref.wddx.php

naholyr

unread,
Apr 6, 2008, 9:25:30 AM4/6/08
to Professional PHP Developers
Last thing for the serialize() format. If there are circular
references, it references the variable with r:X where X is the order
of the variable during serialization (if the variable is the 4th to
have been encountered during serialization it will be referenced as r:
4).
It's not easy to handle, but maybe you can handle this later.

webmouse

unread,
Apr 6, 2008, 12:42:12 PM4/6/08
to Professional PHP Developers
hey ok i have made serialization but there is a problen in
deserialization ...
now i'm a problem
i must create an instance of a class
and then i must set the variables of this class ... how can i do
this..
but there is a problem in here the variable can be private ...
made the serialization very well

it's the result...




<?xml version="1.0"?>
<XmlMenu>
<Name>anasayfa</Name>
<Text>deneme</Text>
<Adres/>
<Image/>
<RoolOverImage/>
<Childs>
<XmlMenu>
<Name>sayfa1</Name>
<Text>sayfa1</Text>
<Adres/>
<Image/>
<RoolOverImage/>
<Childs>
<XmlMenu>
<Name>sayfa12</Name>
<Text>sayfa12</Text>
<Adres/>
<Image/>
<RoolOverImage/>
<Childs/>
<FontStyle/>
<SelectedMenu/>
<SelectedMap/>
<Type/>
</XmlMenu>
</Childs>
<FontStyle/>
<SelectedMenu/>
<SelectedMap/>
<Type/>
</XmlMenu>
<XmlMenu>
<Name>sayfa2</Name>
<Text>sayfa2</Text>
<Adres/>
<Image/>
<RoolOverImage/>
<Childs/>
<FontStyle/>
<SelectedMenu/>
<SelectedMap/>
<Type/>
</XmlMenu>
</Childs>
<FontStyle/>
<SelectedMenu/>
<SelectedMap/>
<Type/>
</XmlMenu>





and code


-------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------
$e= new Serializer();
$ins= new XmlMenu();
$ins->set_Name('anasayfa');
$ins->set_Text('deneme');

$ins2= new XmlMenu();
$ins2->set_Name('sayfa1');
$ins2->set_Text('sayfa1');

$ins3= new XmlMenu();
$ins3->set_Name('sayfa2');
$ins3->set_Text('sayfa2');

$ins12= new XmlMenu();
$ins12->set_Name('sayfa12');
$ins12->set_Text('sayfa12');

$ins2->AddChild($ins12);
$ins->AddChild($ins2);
$ins->AddChild($ins3);

$Ye= $e->SerializeClass($ins,'XmlMenu');
$e->WriteXmlFile($Ye,'c:\menum.xml');

-------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------
class :


class XmlMenu
{
private $Name;
private $Text;
private $Adres;
private $Image;
private $RoolOverImage;
private $Childs;
private $FontStyle;
private $SelectedMenu;
private $SelectedMap;
private $Type;
}


but how can i deserialize this.. .

for example i can take the attributes with name and then create an
instance of XmlMenu class and then sets the properties value...
but the properties are private ...
first how can i create an instance of my class
and how can i get the elements name ... perhaps i can get the
elements values ...
but how can i set the variables...
and how can i set the private variables values ...

please help me with an ezample ...

webmouse

unread,
Apr 6, 2008, 7:08:06 PM4/6/08
to Professional PHP Developers
hey ok i have found the answer myself :D with my little info about php

ok i want to give you the codes
perhaps you like this...








class Serializer
{
private static $Data;

private function GetaArray($arrayValue)
{
foreach ($arrayValue as $Member)
{
$this->SerializeClass($Member,get_class($Member));
}
}
public function Serialize($ObjectInstance,$ClassName)
{
Serializer::$Data.="<Root>";
$this->SerializeClass($ObjectInstance,$ClassName);
Serializer::$Data.="</Root>";
return Serializer::$Data;

}
public function SerializeClass($ObjectInstance,$ClassName)
{


Serializer::$Data.="<".$ClassName.">";
$Class=new ReflectionClass($ClassName);
$ClassArray= ((array)$ObjectInstance);
$Properties=$Class->getProperties();
$i=0;
foreach ($ClassArray as $ClassMember)
{
$prpName= $Properties[$i]->getName();
Serializer::$Data.="<".$prpName.">";
$prpType= gettype($ClassMember);


if ($prpType=='object')
{
$serializerinstance= new Serializer();
$serializerinstance-
>SerializeClass($ClassMember,get_class($ClassMember));
}
if ($prpType=='array')
{
$this->GetaArray($ClassMember);
}
else
{
Serializer::$Data.=$ClassMember;
}
Serializer::$Data.="</".$prpName.">";
$i++;
}
Serializer::$Data.="</".$ClassName.">";
return Serializer::$Data;
}

public function WriteXmlFile($XmlData,$FilePath)
{
$Xml = simplexml_load_string($XmlData);
$Doc=new DOMDocument();
$Doc->loadXML($Xml->asXML());
$Doc->save($FilePath);
}
public function DeserializeClass($FilePath)
{
$Xml=simplexml_load_file($FilePath);
return $this->Deserialize($Xml);
}
public function Deserialize($Root)
{
$result=null;
$counter=0;
foreach ($Root as $member)
{
$instance = new ReflectionClass($member->getName());
$ins=$instance->newInstance();
foreach ($member as $child)
{
$rp=$instance->getMethod("set_".$child->getName());
if (count($child->children())==0)
{
$rp->invoke($ins,$child);
}
else
{
$rp->invoke($ins,$this->Deserialize($child->children()));
echo $child;
}
}
if (count($Root)==1) {
return $ins;
}
else
{
$result[$counter]=$ins;
$counter++;
}
if ($counter==count($Root)) {
return $result;
}
}
}


}




----------------------------------------------------------------------------
and using


$myclassins= new Serializer();
$Xml= $myclassins->Serialize($instance,'classname');
$thing->WriteXmlFile($Xml,'c:\ersin.xml');
$result=$myclassins->DeserializeClass('c:\ersin.xml');

and the result is your object, instance of your class...
thanks every body....

naholyr

unread,
Apr 9, 2008, 2:57:16 AM4/9/08
to Professional PHP Developers
Nice method, I didn't know you could set private attributes using
ReflectionClass :)
> ---------------------------------------------------------------------------­-

tomas...@gmail.com

unread,
May 28, 2008, 6:37:40 PM5/28/08
to Professional PHP Developers
Really nice work. But I do little change in your code. For me it is
useless specify class name every time.
My change:

public function Serialize($ObjectInstance, $ClassName=null)
{
if ($ClassName==null)
{
$ClassName=get_class($ObjectInstance);
Reply all
Reply to author
Forward
0 new messages