|
18 | 18 | use InvalidArgumentException; |
19 | 19 | use Koded\Stdlib\Serializer; |
20 | 20 | use Throwable; |
21 | | -use function array_keys; |
| 21 | +use function array_is_list; |
22 | 22 | use function count; |
23 | | -use function ctype_digit; |
24 | 23 | use function current; |
25 | 24 | use function error_log; |
26 | 25 | use function filter_var; |
|
31 | 30 | use function is_iterable; |
32 | 31 | use function is_numeric; |
33 | 32 | use function is_object; |
34 | | -use function join; |
35 | 33 | use function Koded\Stdlib\{json_serialize, json_unserialize}; |
36 | 34 | use function key; |
37 | 35 | use function preg_match; |
| 36 | +use function str_contains; |
38 | 37 | use function str_starts_with; |
39 | 38 | use function substr; |
40 | 39 | use function trim; |
@@ -130,14 +129,26 @@ private function buildXml( |
130 | 129 | // node value |
131 | 130 | $parent->nodeValue = $data; |
132 | 131 | } elseif (false === $isKeyNumeric && is_array($data)) { |
133 | | - if (ctype_digit(join('', array_keys($data)))) { |
| 132 | + /* |
| 133 | + * If the data is an associative array (with numeric keys) |
| 134 | + * the structure is transformed to "item" nodes: |
| 135 | + * <item key="0">$key0</item> |
| 136 | + * <item key="1">$key1</item> |
| 137 | + * by appending it to the parent node (if any) |
| 138 | + */ |
| 139 | + if (array_is_list($data)) { |
134 | 140 | foreach ($data as $d) { |
135 | 141 | $this->appendNode($document, $parent, $d, $key); |
136 | 142 | } |
137 | 143 | } else { |
138 | 144 | $this->appendNode($document, $parent, $data, $key); |
139 | 145 | } |
140 | | - } elseif ($isKeyNumeric) { |
| 146 | + } elseif ($isKeyNumeric || false === $this->hasValidName($key)) { |
| 147 | + /* If the key is not a valid XML tag name, |
| 148 | + * transform the key to "item" node: |
| 149 | + * <item key="$key">$value</item> |
| 150 | + * by appending it to the parent node (if any) |
| 151 | + */ |
141 | 152 | $this->appendNode($document, $parent, $data, 'item', $key); |
142 | 153 | } else { |
143 | 154 | $this->appendNode($document, $parent, $data, $key); |
@@ -307,4 +318,11 @@ private function getValueByType(mixed $value): mixed |
307 | 318 | } |
308 | 319 | return $value[$this->val]; |
309 | 320 | } |
| 321 | + |
| 322 | + private function hasValidName(int|string $key): bool |
| 323 | + { |
| 324 | + return $key && |
| 325 | + !str_contains($key, ' ') && |
| 326 | + preg_match('~^[\pL_][\pL0-9._:-]*$~ui', $key); |
| 327 | + } |
310 | 328 | } |
0 commit comments