我需要将我收到的一些XML反序列化为一个对象。我使用SimpleXML来做到这一点。收到的一些XML的一个例子是:
<?xml version="1.0" encoding="UTF-8"?>
<coupons type="array">
<coupon>
<coupon_code>baz</coupon_code>
<name>baz</name>
<discount_type>percent</discount_type>
<discount_percent type="integer">20</discount_percent>
<plan_codes type="array">
<plan_code>plus</plan_code>
<plan_code>pro</plan_code>
</plan_codes>
</coupon>
<coupon>
<coupon_code>test</coupon_code>
<name>Test</name>
<discount_type>dollars</discount_type>
<discount_in_cents>
<USD type="integer">2000</USD>
<EUR type="integer">1500</USD>
</discount_in_cents>
<plan_codes type="array">
<plan_code>plus</plan_code>
</plan_codes>
</coupon>
</coupons>
在这段XML中,有3种类型的数组:<coupons>
是<coupon>
的数组。 <coupon>
也有2个数组:<plan_codes>
(这是一个平面数组)和<discount_in_cents>
是一个关联数组。
我的反序列化器如何工作:我从XML创建一个SimpleXMLElement并将其传递给一个函数visitElement
,它接受一个SimpleXMLElement,在这种情况下类型为array<Model\Coupon>
,表明它是一个{的数组{1}}对象。
在我的Model\Coupon
中,我检查类型是否是现有类,如果是,我创建该类的新实例并获取该模型的配置,配置告诉我哪些子项需要反序列化为哪个对象变量。 visitElement
看起来像这样:
visitElement
这样,我有一个很好的递归方式来反序列化其他XML,它可能有嵌套对象(例如,Account XML有一个嵌套在其中的Address对象)。
我的public function visitElement($element, $type)
{
// it is possible the element is not available
if (!$element) {
return null;
} else {
// get the value based on it's mapped type
switch ($type) {
case 'string':
return $this->visitString($element);
break;
// ...
// other cases
// ...
default: // catch other cases
if (class_exists($type)) {
// We mapped to an existing class
return $this->visitModel($type, $element);
} elseif ($this->isArrayType($type, $arrayType, $keepKey)) {
// We mapped to an array<type>
return $this->visitArray($arrayType, $element, $keepKey);
} else {
// A type we can't handle
return null;
}
}
}
}
已配置为Model\Coupon
和<plan_codes>
分别被视为<discount_in_cents>
和array<string>
。
这是我的array<integer>
功能:
visitArray
这一切都很美妙。我得到一个包含2个protected function visitArray($type, $element, $keepKey = false)
{
$value = null;
$i = 0;
foreach ($element->children() as $key => $child) {
$k = $keepKey ? $key : $i++;
$value[$k] = $this->visitElement($child, $type);
}
return $value;
}
个对象的数组,第二个对象有一个看起来像['USD'=&gt;的discount_in_cents数组。 2000年,'EUR'=&gt; 1500],但它不适用于计划代码...
当我var_dump那些,我得到
Model\Coupon
和
array (size=2)
0 => null
1 => null
是否有任何理由为什么循环array (size=1)
0 => null
会产生与<plan_codes>
或<coupons>
不同的结果/子女?
目前,我在<discount_in_cents>
中实施了一种解决方法,如下所示:
visitArray