@@ -94,26 +94,27 @@ public function decode($data, $format, array $context = array())
94
94
}
95
95
}
96
96
97
- $ xml = simplexml_import_dom ( $ dom) ;
97
+ $ rootNode = $ dom-> firstChild ;
98
98
99
- if ($ error = libxml_get_last_error ()) {
100
- throw new UnexpectedValueException ($ error ->message );
99
+ // todo: throw an exception if the root node name is not correctly configured (bc)
100
+
101
+ if ($ rootNode ->hasChildNodes ()) {
102
+ return $ this ->parseXml ($ rootNode );
101
103
}
102
104
103
- if (!$ xml ->count ()) {
104
- if (!$ xml ->attributes ()) {
105
- return (string ) $ xml ;
106
- }
107
- $ data = array ();
108
- foreach ($ xml ->attributes () as $ attrkey => $ attr ) {
109
- $ data ['@ ' .$ attrkey ] = (string ) $ attr ;
110
- }
111
- $ data ['# ' ] = (string ) $ xml ;
105
+ if (!$ rootNode ->hasAttributes ()) {
106
+ return $ rootNode ->nodeValue ;
107
+ }
112
108
113
- return $ data ;
109
+ $ data = array ();
110
+
111
+ foreach ($ rootNode ->attributes as $ attrKey => $ attr ) {
112
+ $ data ['@ ' .$ attrKey ] = $ attr ->nodeValue ;
114
113
}
115
114
116
- return $ this ->parseXml ($ xml );
115
+ $ data ['# ' ] = $ rootNode ->nodeValue ;
116
+
117
+ return $ data ;
117
118
}
118
119
119
120
/**
@@ -230,54 +231,107 @@ final protected function isElementNameValid($name)
230
231
}
231
232
232
233
/**
233
- * Parse the input SimpleXmlElement into an array.
234
+ * Parse the input DOMNode into an array.
234
235
*
235
- * @param \SimpleXmlElement $node xml to parse
236
+ * @param \DOMNode $node xml to parse
236
237
*
237
238
* @return array
238
239
*/
239
- private function parseXml (\SimpleXmlElement $ node )
240
+ private function parseXml (\DOMNode $ node )
240
241
{
241
- $ data = array ();
242
- if ($ node ->attributes ()) {
243
- foreach ($ node ->attributes () as $ attrkey => $ attr ) {
244
- $ data ['@ ' .$ attrkey ] = (string ) $ attr ;
245
- }
242
+ $ data = $ this ->parseXmlAttributes ($ node );
243
+
244
+ $ value = $ this ->parseXmlValue ($ node );
245
+
246
+ if (!count ($ data )) {
247
+ return $ value ;
246
248
}
247
- foreach ($ node ->children () as $ key => $ subnode ) {
248
- if ($ subnode ->count ()) {
249
- $ value = $ this ->parseXml ($ subnode );
250
- } elseif ($ subnode ->attributes ()) {
251
- $ value = array ();
252
- foreach ($ subnode ->attributes () as $ attrkey => $ attr ) {
253
- $ value ['@ ' .$ attrkey ] = (string ) $ attr ;
254
- }
255
- $ value ['# ' ] = (string ) $ subnode ;
249
+
250
+ if (!is_array ($ value )) {
251
+ $ data ['# ' ] = $ value ;
252
+
253
+ return $ data ;
254
+ }
255
+
256
+ if (1 === count ($ value ) && key ($ value )) {
257
+ $ data [key ($ value )] = current ($ value );
258
+
259
+ return $ data ;
260
+ }
261
+
262
+ foreach ($ value as $ key => $ val ) {
263
+ $ data [$ key ] = $ val ;
264
+ }
265
+
266
+ return $ data ;
267
+ }
268
+
269
+ /**
270
+ * Parse the input DOMNode attributes into an array
271
+ *
272
+ * @param \DOMNode $node xml to parse
273
+ *
274
+ * @return array
275
+ */
276
+ private function parseXmlAttributes (\DOMNode $ node )
277
+ {
278
+ if (!$ node ->hasAttributes ()) {
279
+ return array ();
280
+ }
281
+
282
+ $ data = array ();
283
+
284
+ foreach ($ node ->attributes as $ attrkey => $ attr ) {
285
+ if (ctype_digit ($ attr ->nodeValue )) {
286
+ $ data ['@ ' .$ attrkey ] = (int ) $ attr ->nodeValue ;
256
287
} else {
257
- $ value = ( string ) $ subnode ;
288
+ $ data [ ' @ ' . $ attrkey ] = $ attr -> nodeValue ;
258
289
}
290
+ }
259
291
260
- if ($ key === 'item ' ) {
261
- if (isset ($ value ['@key ' ])) {
262
- if (isset ($ value ['# ' ])) {
263
- $ data [$ value ['@key ' ]] = $ value ['# ' ];
264
- } else {
265
- $ data [$ value ['@key ' ]] = $ value ;
266
- }
292
+ return $ data ;
293
+ }
294
+
295
+ /**
296
+ * Parse the input DOMNode value (content and children) into an array or a string
297
+ *
298
+ * @param \DOMNode $node xml to parse
299
+ *
300
+ * @return array|string
301
+ */
302
+ private function parseXmlValue (\DOMNode $ node )
303
+ {
304
+ if (!$ node ->hasChildNodes ()) {
305
+ return $ node ->nodeValue ;
306
+ }
307
+
308
+ if (1 === $ node ->childNodes ->length && XML_TEXT_NODE === $ node ->firstChild ->nodeType ) {
309
+ return $ node ->firstChild ->nodeValue ;
310
+ }
311
+
312
+ $ value = array ();
313
+
314
+ foreach ($ node ->childNodes as $ subnode ) {
315
+ $ val = $ this ->parseXml ($ subnode );
316
+
317
+ if ('item ' === $ subnode ->nodeName && isset ($ val ['@key ' ])) {
318
+ if (isset ($ val ['# ' ])) {
319
+ $ value [$ val ['@key ' ]] = $ val ['# ' ];
267
320
} else {
268
- $ data [ ' item ' ][ ] = $ value ;
321
+ $ value [ $ val [ ' @key ' ] ] = $ val ;
269
322
}
270
- } elseif (array_key_exists ($ key , $ data ) || $ key == "entry " ) {
271
- if ((false === is_array ($ data [$ key ])) || (false === isset ($ data [$ key ][0 ]))) {
272
- $ data [$ key ] = array ($ data [$ key ]);
273
- }
274
- $ data [$ key ][] = $ value ;
275
323
} else {
276
- $ data [ $ key ] = $ value ;
324
+ $ value [ $ subnode -> nodeName ][] = $ val ;
277
325
}
278
326
}
279
327
280
- return $ data ;
328
+ foreach ($ value as $ key => $ val ) {
329
+ if (is_array ($ val ) && 1 === count ($ val )) {
330
+ $ value [$ key ] = current ($ val );
331
+ }
332
+ }
333
+
334
+ return $ value ;
281
335
}
282
336
283
337
/**
0 commit comments