/
XmlTypeDecoder.php
106 lines (82 loc) · 2.53 KB
/
XmlTypeDecoder.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
<?php
declare(strict_types=1);
namespace Chubbyphp\Deserialization\Decoder;
use Chubbyphp\Deserialization\DeserializerRuntimeException;
/**
* @deprecated use JsonxTypeDecoder instead
*/
final class XmlTypeDecoder implements TypeDecoderInterface
{
public function getContentType(): string
{
return 'application/xml';
}
/**
* @throws DeserializerRuntimeException
*/
public function decode(string $data): array
{
$document = new \DOMDocument();
if (!@$document->loadXML($data)) {
throw DeserializerRuntimeException::createNotParsable($this->getContentType());
}
return $this->transformType($document->getElementsByTagName('object')->item(0));
}
private function transformType(\DOMElement $node): array
{
$data = [];
$childNodes = [];
foreach ($node->childNodes as $childNode) {
if ($childNode instanceof \DOMElement) {
$childNodes[] = $childNode;
}
}
foreach ($childNodes as $childNode) {
if (0 === $childNode->childNodes->length) {
$data[$this->getKey($childNode)] = null;
continue;
}
if (1 === $childNode->childNodes->length) {
$data[$this->getKey($childNode)] = $this->getValue($childNode);
continue;
}
if ('object' === $childNode->nodeName
&& $childNode->hasAttribute('type')
&& !$childNode->hasAttribute('key')
) {
return $this->transformType($childNode);
}
$data[$this->getKey($childNode)] = $this->transformType($childNode);
}
if ('object' === $node->nodeName && $node->hasAttribute('type')) {
$data['_type'] = $node->getAttribute('type');
}
return $data;
}
/**
* @return string|int
*/
private function getKey(\DOMElement $node)
{
if ($node->hasAttribute('key')) {
return (int) $node->getAttribute('key');
}
$name = $node->nodeName;
if (0 === strpos($name, 'meta-')) {
$name = '_'.substr($name, 5);
}
return $name;
}
/**
* @return bool|string
*/
private function getValue(\DOMElement $node)
{
$value = $node->nodeValue;
if ('boolean' === $type = $node->getAttribute('type')) {
return 'true' === $value;
}
settype($value, $type);
return $value;
}
}