Skip to content
This repository
Browse code

Applying patch from 'Stefano Rosanelli' which fixes Xml::toArray() gr…

…eatly improving

its ability to convert xml documents.  Fixes #1667
  • Loading branch information...
commit 5105d5c9f8077e87d4b54a021eac4bc971fcb8dc 1 parent f0b7066
Mark Story authored April 21, 2011
49  cake/libs/xml.php
@@ -660,11 +660,11 @@ function toString($options = array(), $depth = 0) {
660 660
  */
661 661
 	function toArray($camelize = true) {
662 662
 		$out = $this->attributes;
663  
-		$multi = null;
664 663
 
665 664
 		foreach ($this->children as $child) {
666 665
 			$key = $camelize ? Inflector::camelize($child->name) : $child->name;
667 666
 
  667
+			$leaf = false;
668 668
 			if (is_a($child, 'XmlTextNode')) {
669 669
 				$out['value'] = $child->value;
670 670
 				continue;
@@ -673,47 +673,34 @@ function toArray($camelize = true) {
673 673
 				if ($child->attributes) {
674 674
 					$value = array_merge(array('value' => $value), $child->attributes);
675 675
 				}
676  
-				if (isset($out[$child->name]) || isset($multi[$key])) {
677  
-					if (!isset($multi[$key])) {
678  
-						$multi[$key] = array($out[$child->name]);
679  
-						unset($out[$child->name]);
680  
-					}
681  
-					$multi[$key][] = $value;
682  
-				} else {
683  
-					$out[$child->name] = $value;
  676
+				if (count($child->children) == 1) {
  677
+					$leaf = true;
684 678
 				}
685  
-				continue;
686 679
 			} elseif (count($child->children) === 0 && $child->value == '') {
687 680
 				$value = $child->attributes;
688  
-				if (isset($out[$key]) || isset($multi[$key])) {
689  
-					if (!isset($multi[$key])) {
690  
-						$multi[$key] = array($out[$key]);
691  
-						//unset($out[$key]);
692  
-					}
693  
-					$multi[$key][] = $value;
694  
-				} elseif (!empty($value)) {
695  
-					$out[$key] = $value;
696  
-				} else {
697  
-					$out[$child->name] = $value;
  681
+				if (empty($value)) {
  682
+					$leaf = true;
698 683
 				}
699  
-				continue;
700 684
 			} else {
701 685
 				$value = $child->toArray($camelize);
702 686
 			}
703 687
 
704  
-			if (!isset($out[$key])) {
705  
-				$out[$key] = $value;
706  
-			} else {
707  
-				if (!is_array($out[$key]) || !isset($out[$key][0])) {
  688
+			if (isset($out[$key])) {
  689
+				if(!isset($out[$key][0]) || !is_array($out[$key]) || !is_int(key($out[$key]))) {
708 690
 					$out[$key] = array($out[$key]);
709  
-				}
  691
+				} 
710 692
 				$out[$key][] = $value;
  693
+			} elseif (isset($out[$child->name])) {
  694
+				$t = $out[$child->name];
  695
+				unset($out[$child->name]);
  696
+				$out[$key] = array($t);
  697
+				$out[$key][] = $value;
  698
+			} elseif ($leaf) {
  699
+				$out[$child->name] = $value;
  700
+			} else {
  701
+				$out[$key] = $value;
711 702
 			}
712 703
 		}
713  
-
714  
-		if (isset($multi)) {
715  
-			$out = array_merge($out, $multi);
716  
-		}
717 704
 		return $out;
718 705
 	}
719 706
 /**
@@ -1400,4 +1387,4 @@ function &getInstance() {
1400 1387
 		return $instance[0];
1401 1388
 	}
1402 1389
 }
1403  
-?>
  1390
+?>
192  cake/tests/cases/libs/xml.test.php
@@ -1390,5 +1390,195 @@ function testMemoryLeakInConstructor() {
1390 1390
 		$end = memory_get_usage();
1391 1391
 		$this->assertWithinMargin($start, $end, 3600, 'Memory leaked %s');
1392 1392
 	}
  1393
+
  1394
+/**
  1395
+ * Test toArray with alternate inputs.
  1396
+ *
  1397
+ * @return void
  1398
+ */
  1399
+	function testToArrayAlternate() {
  1400
+		$sXml = 
  1401
+		'<t1>
  1402
+		 	<t2>A</t2>
  1403
+      		<t2><t3>AAA</t3>B</t2>
  1404
+	  		<t2>C</t2>
  1405
+		</t1>';
  1406
+		$xml = new Xml($sXml);
  1407
+		$result = $xml->toArray();
  1408
+		$expected = array(
  1409
+			'T1' => array(
  1410
+				'T2' => array(
  1411
+					'A',
  1412
+					array('t3' => 'AAA', 'value' => 'B'),
  1413
+					'C'
  1414
+			)
  1415
+		)
  1416
+		);
  1417
+		$this->assertIdentical($result, $expected);
  1418
+		$result = $xml->toArray(false);
  1419
+		$expected = array(
  1420
+			't1' => array(
  1421
+				't2' => array(
  1422
+					'A',
  1423
+					array('t3' => 'AAA', 'value' => 'B'),
  1424
+					'C'
  1425
+				)
  1426
+			)
  1427
+		);
  1428
+		$this->assertIdentical($result, $expected);
  1429
+		
  1430
+		$sXml = 
  1431
+		'<t1>
  1432
+		 	<t2>A</t2>
  1433
+	  		<t2>B</t2>
  1434
+      		<t2>
  1435
+	         	<t3>CCC</t3>
  1436
+	      	</t2>
  1437
+		</t1>';
  1438
+		$xml = new Xml($sXml);
  1439
+		$result = $xml->toArray();
  1440
+		$expected = array(
  1441
+			'T1' => array(
  1442
+				'T2' => array(
  1443
+					'A',
  1444
+					'B',
  1445
+					array('t3' => 'CCC'),
  1446
+				)
  1447
+			)
  1448
+		);
  1449
+		$this->assertIdentical($result, $expected);
  1450
+		$result = $xml->toArray(false);
  1451
+		$expected = array(
  1452
+			't1' => array(
  1453
+				't2' => array(
  1454
+					'A',
  1455
+					'B',
  1456
+					array('t3' => 'CCC'),
  1457
+				)
  1458
+			)
  1459
+		);
  1460
+		$this->assertIdentical($result, $expected);
  1461
+		
  1462
+		$sXml = 
  1463
+		'<t1>
  1464
+		 <t2>A</t2>
  1465
+		 <t2></t2>
  1466
+		 <t2>C</t2>
  1467
+		</t1>';
  1468
+		$xml = new Xml($sXml);
  1469
+		$result = $xml->toArray();
  1470
+		$expected = array(
  1471
+			'T1' => array(
  1472
+				'T2' => array(
  1473
+					'A',
  1474
+					array(),
  1475
+					'C'
  1476
+				)
  1477
+			)
  1478
+		);
  1479
+		$this->assertIdentical($result, $expected);
  1480
+
  1481
+		$result = $xml->toArray(false);
  1482
+		$expected = array(
  1483
+			't1' => array(
  1484
+				't2' => array(
  1485
+					'A',
  1486
+					array(),
  1487
+					'C'
  1488
+				)
  1489
+			)
  1490
+		);
  1491
+		$this->assertIdentical($result, $expected);
  1492
+		
  1493
+		$sXml = 
  1494
+		'<stuff>
  1495
+    <foo name="abc-16" profile-id="Default" />
  1496
+    <foo name="abc-17" profile-id="Default" >
  1497
+        <bar id="HelloWorld" />
  1498
+    </foo>
  1499
+    <foo name="abc-asdf" profile-id="Default" />
  1500
+    <foo name="cba-1A" profile-id="Default">
  1501
+        <bar id="Baz" />
  1502
+    </foo>
  1503
+    <foo name="cba-2A" profile-id="Default">
  1504
+        <bar id="Baz" />
  1505
+    </foo>
  1506
+    <foo name="qa" profile-id="Default" />
  1507
+</stuff>';
  1508
+		$xml = new Xml($sXml);
  1509
+		$result = $xml->toArray();
  1510
+		$expected = array(
  1511
+			'Stuff' => array(
  1512
+				'Foo' => array(
  1513
+					array('name' => 'abc-16', 'profile-id' => 'Default'),
  1514
+					array('name' => 'abc-17', 'profile-id' => 'Default', 
  1515
+						'Bar' => array('id' => 'HelloWorld')),
  1516
+					array('name' => 'abc-asdf', 'profile-id' => 'Default'),
  1517
+					array('name' => 'cba-1A', 'profile-id' => 'Default', 
  1518
+						'Bar' => array('id' => 'Baz')),
  1519
+					array('name' => 'cba-2A', 'profile-id' => 'Default', 
  1520
+						'Bar' => array('id' => 'Baz')),
  1521
+					array('name' => 'qa', 'profile-id' => 'Default'),
  1522
+				)
  1523
+			)
  1524
+		);
  1525
+		$this->assertIdentical($result, $expected);
  1526
+		$result = $xml->toArray(false);
  1527
+		$expected = array(
  1528
+			'stuff' => array(
  1529
+				'foo' => array(
  1530
+					array('name' => 'abc-16', 'profile-id' => 'Default'),
  1531
+					array('name' => 'abc-17', 'profile-id' => 'Default', 
  1532
+						'bar' => array('id' => 'HelloWorld')),
  1533
+					array('name' => 'abc-asdf', 'profile-id' => 'Default'),
  1534
+					array('name' => 'cba-1A', 'profile-id' => 'Default', 
  1535
+						'bar' => array('id' => 'Baz')),
  1536
+					array('name' => 'cba-2A', 'profile-id' => 'Default', 
  1537
+						'bar' => array('id' => 'Baz')),
  1538
+					array('name' => 'qa', 'profile-id' => 'Default'),
  1539
+				)
  1540
+			)
  1541
+		);
  1542
+		$this->assertIdentical($result, $expected);
  1543
+		
  1544
+		
  1545
+		$sXml = 
  1546
+		'<root>
  1547
+  <node name="first" />
  1548
+  <node name="second"><subnode name="first sub" /><subnode name="second sub" /></node>
  1549
+  <node name="third" />
  1550
+</root>';
  1551
+		$xml = new Xml($sXml);
  1552
+		$result = $xml->toArray();
  1553
+		$expected = array(
  1554
+			'Root' => array(
  1555
+				'Node' => array(
  1556
+					array('name' => 'first'),
  1557
+					array('name' => 'second', 
  1558
+						'Subnode' => array(
  1559
+							array('name' => 'first sub'), 
  1560
+							array('name' => 'second sub'))),
  1561
+					array('name' => 'third'),
  1562
+				)
  1563
+			)
  1564
+		);
  1565
+		$this->assertIdentical($result, $expected);
  1566
+		
  1567
+		$result = $xml->toArray(false);
  1568
+		$expected = array(
  1569
+			'root' => array(
  1570
+				'node' => array(
  1571
+					array('name' => 'first'),
  1572
+					array('name' => 'second', 
  1573
+						'subnode' => array(
  1574
+							array('name' => 'first sub'), 
  1575
+							array('name' => 'second sub'))),
  1576
+					array('name' => 'third'),
  1577
+				)
  1578
+			)
  1579
+		);
  1580
+		$this->assertIdentical($result, $expected);
  1581
+	}
  1582
+	
1393 1583
 }
1394  
-?>
  1584
+?>

0 notes on commit 5105d5c

Please sign in to comment.
Something went wrong with that request. Please try again.