-
Notifications
You must be signed in to change notification settings - Fork 77
External object serializers. #61
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Any chanche we can get the classmap beeing used for reading and writing? |
|
That wouldn't make a lot of sense, because during reading we don't know yet which class needs to be created. All we have is the element name. |
|
Oh, obviously you are right ;-) |
|
one thing which bugs me... class ErpOrderService extends Sabre\Xml\Service {
public $elementMap = array(
'{http://b2bOrder.complex.de}order_response' => function (Sabre\Xml\Reader $reader) use ($popoDeserializer) {
return $popoDeserializer($reader, new OrderResponse(), XMLNS_ORDER);
},
'{http://b2bOrder.complex.de}order_status' => function (Sabre\Xml\Reader $reader) use ($popoDeserializer) {
return $popoDeserializer($reader, new OrderStatus(), XMLNS_ORDER);
},
);
}is not valid php, as I cannot use closures on the public field here |
|
ok, wil change it to $erpOrderService = new Sabre\Xml\Service();
$erpOrderService->elementMap = array(
'{'. XMLNS_ORDER .'}order_response' => function (Sabre\Xml\Reader $reader) use ($popoDeserializer) {
return $popoDeserializer($reader, new OrderResponse(), XMLNS_ORDER);
},
'{'. XMLNS_ORDER .'}order_status' => function (Sabre\Xml\Reader $reader) use ($popoDeserializer) {
return $popoDeserializer($reader, new OrderStatus(), XMLNS_ORDER);
},
);like the Reader/Writer examples |
|
... progress... $xml = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<order_response xmlns="http://b2bOrder.complex.de">
<request_id>4711</request_id>
<order_id>54752</order_id>
<order_status xmlns="http://b2bOrder.complex.de">
<status>INITIALIZED</status>
</order_status>
<success>true</success>
</order_response>';
$popoDeserializer = function(Sabre\Xml\Reader $reader, $popo, $namespace)
{
if ($reader->isEmptyElement) {
throw new Exception(__CLASS__ . ' does not support empty elements');
}
$reader->read();
do {
if ($reader->nodeType === Sabre\Xml\Reader::ELEMENT && $reader->namespaceURI == $namespace) {
$popo->{$reader->localName} = $reader->parseCurrentElement()['value'];
} else {
$reader->read();
}
} while ($reader->nodeType !== Sabre\Xml\Reader::END_ELEMENT);
$reader->read();
return $popo;
};
$popoSerializer = function(Sabre\Xml\Writer $writer, $popo, $namespace) {
foreach(get_object_vars($popo) as $key => $val) {
$writer->writeElement('{'. $namespace .'}' . $key, $val);
}
};
class OrderResponse
{
public $request_id;
public $order_id;
public $order_status;
public $success;
}
class OrderStatus
{
public $status;
}
define("XMLNS_ORDER", "http://b2bOrder.complex.de");
$erpOrderService = new Sabre\Xml\Service();
$erpOrderService->namespaceMap[XMLNS_ORDER] = '';
// how to read xml into objects
$erpOrderService->elementMap = array(
'{'. XMLNS_ORDER .'}order_response' => function (Sabre\Xml\Reader $reader) use ($popoDeserializer) {
return $popoDeserializer($reader, new OrderResponse(), XMLNS_ORDER);
},
'{'. XMLNS_ORDER .'}order_status' => function (Sabre\Xml\Reader $reader) use ($popoDeserializer) {
return $popoDeserializer($reader, new OrderStatus(), XMLNS_ORDER);
},
);
// how to create xml from obejects
$erpOrderService->classMap = array(
'OrderResponse' => function(Sabre\Xml\Writer $writer, $orderResponse) use ($popoSerializer) {
/** @var $orderResponse OrderResponse */
$popoSerializer($writer, $orderResponse, XMLNS_ORDER);
},
'OrderStatus' => function(Sabre\Xml\Writer $writer, $orderStatus) use ($popoSerializer) {
/** @var $orderStatus OrderStatus */
$popoSerializer($writer, $orderStatus, XMLNS_ORDER);
}
);
var_dump($xml);
$orderResp = $erpOrderService->parse($xml);
var_dump($orderResp);
var_dump($erpOrderService->write(get_class($orderResp), $orderResp));output string(331) "<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<order_response xmlns="http://b2bOrder.complex.de">
<request_id>4711</request_id>
<order_id>54752</order_id>
<order_status xmlns="http://b2bOrder.complex.de">
<status>INITIALIZED</status>
</order_status>
<success>true</success>
</order_response>"
object(OrderResponse)#11 (4) {
["request_id"]=>
string(4) "4711"
["order_id"]=>
string(5) "54752"
["order_status"]=>
object(OrderStatus)#12 (1) {
["status"]=>
string(11) "INITIALIZED"
}
["success"]=>
string(4) "true"
}
string(248) "<?xml version="1.0"?>
<OrderResponse xmlns="http://b2bOrder.complex.de">
<:request_id>4711</:request_id>
<:order_id>54752</:order_id>
<:order_status>
<:status>INITIALIZED</:status>
</:order_status>
<:success>true</:success>
</OrderResponse>
"except the In contrast to your usual convention that a element should not emit the xml-element for itself, in case of having a external deserializer it would make sense to have the serializer emit the whole element... wdyt? (in case we agree here, I cannot use the |
Alternatively you could also have set them in the constructor.
What's with that
Personally I would not break the rule, but if you think you have good reasons to do so, you should ;) |
I dont know why. The above code is runnable, maybe it helps to repro the problem |
|
I guess the I do this to not get a namespace (inspired by the docs from http://sabre.io/xml/writing/) |
|
Can you try |
|
@evert you are right, we need send a PR which fixes the example code. It also fixes another error with the code. So after all this we have a working code: $xml = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<order_response xmlns="http://b2bOrder.complex.de">
<request_id>4711</request_id>
<order_id>54752</order_id>
<order_status xmlns="http://b2bOrder.complex.de">
<status>INITIALIZED</status>
</order_status>
<success>true</success>
</order_response>';
$popoDeserializer = function(Sabre\Xml\Reader $reader, $popo, $namespace)
{
if ($reader->isEmptyElement) {
throw new Exception(__CLASS__ . ' does not support empty elements');
}
$reader->read();
do {
if ($reader->nodeType === Sabre\Xml\Reader::ELEMENT && $reader->namespaceURI == $namespace) {
$popo->{$reader->localName} = $reader->parseCurrentElement()['value'];
} else {
$reader->read();
}
} while ($reader->nodeType !== Sabre\Xml\Reader::END_ELEMENT);
$reader->read();
return $popo;
};
$popoSerializer = function(Sabre\Xml\Writer $writer, $popo, $namespace) {
foreach(get_object_vars($popo) as $key => $val) {
$writer->writeElement('{'. $namespace .'}' . $key, $val);
}
};
class OrderResponse
{
public $request_id;
public $order_id;
public $order_status;
public $success;
}
class OrderStatus
{
public $status;
}
define("XMLNS_ORDER", "http://b2bOrder.complex.de");
$erpOrderService = new Sabre\Xml\Service();
$erpOrderService->namespaceMap[XMLNS_ORDER] = null;
// how to read xml into objects
$erpOrderService->elementMap = array(
'{'. XMLNS_ORDER .'}order_response' => function (Sabre\Xml\Reader $reader) use ($popoDeserializer) {
return $popoDeserializer($reader, new OrderResponse(), XMLNS_ORDER);
},
'{'. XMLNS_ORDER .'}order_status' => function (Sabre\Xml\Reader $reader) use ($popoDeserializer) {
return $popoDeserializer($reader, new OrderStatus(), XMLNS_ORDER);
},
);
// how to create xml from obejects
$erpOrderService->classMap = array(
'OrderResponse' => function(Sabre\Xml\Writer $writer, $orderResponse) use ($popoSerializer) {
/** @var $orderResponse OrderResponse */
$popoSerializer($writer, $orderResponse, XMLNS_ORDER);
},
'OrderStatus' => function(Sabre\Xml\Writer $writer, $orderStatus) use ($popoSerializer) {
/** @var $orderStatus OrderStatus */
$popoSerializer($writer, $orderStatus, XMLNS_ORDER);
}
);
echo "<xmp>";
var_dump($xml);
$orderResp = $erpOrderService->parse($xml);
var_dump($orderResp);
var_dump($erpOrderService->write(get_class($orderResp), $orderResp));output string(323) "<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<order_response xmlns="http://b2bOrder.complex.de">
<request_id>4711</request_id>
<order_id>54752</order_id>
<order_status xmlns="http://b2bOrder.complex.de">
<status>INITIALIZED</status>
</order_status>
<success>true</success>
</order_response>"
object(OrderResponse)#10 (4) {
["request_id"]=>
string(4) "4711"
["order_id"]=>
string(5) "54752"
["order_status"]=>
object(OrderStatus)#11 (1) {
["status"]=>
string(11) "INITIALIZED"
}
["success"]=>
string(4) "true"
}
string(238) "<?xml version="1.0"?>
<OrderResponse xmlns="http://b2bOrder.complex.de">
<request_id>4711</request_id>
<order_id>54752</order_id>
<order_status>
<status>INITIALIZED</status>
</order_status>
<success>true</success>
</OrderResponse>
"do you think this kind of popo serializer/deserializer is something which should be shipped with sabre/xml or is it to specific for my current app? |
|
I would definitely think it's a good idea to have this as a core feature btw! |
|
Perhaps we can integrate this in the |
|
Agree that having it in the Service class is a good idea. Its the place where this kind of api-sugar should happen. PR incoming |
cc: @staabm. What do you think?