From 5105d5c9f8077e87d4b54a021eac4bc971fcb8dc Mon Sep 17 00:00:00 2001 From: mark_story Date: Thu, 21 Apr 2011 22:38:41 -0400 Subject: [PATCH] Applying patch from 'Stefano Rosanelli' which fixes Xml::toArray() greatly improving its ability to convert xml documents. Fixes #1667 --- cake/libs/xml.php | 49 +++----- cake/tests/cases/libs/xml.test.php | 192 ++++++++++++++++++++++++++++- 2 files changed, 209 insertions(+), 32 deletions(-) diff --git a/cake/libs/xml.php b/cake/libs/xml.php index 1151e58805d..71bd3d5bd98 100644 --- a/cake/libs/xml.php +++ b/cake/libs/xml.php @@ -660,11 +660,11 @@ function toString($options = array(), $depth = 0) { */ function toArray($camelize = true) { $out = $this->attributes; - $multi = null; foreach ($this->children as $child) { $key = $camelize ? Inflector::camelize($child->name) : $child->name; + $leaf = false; if (is_a($child, 'XmlTextNode')) { $out['value'] = $child->value; continue; @@ -673,47 +673,34 @@ function toArray($camelize = true) { if ($child->attributes) { $value = array_merge(array('value' => $value), $child->attributes); } - if (isset($out[$child->name]) || isset($multi[$key])) { - if (!isset($multi[$key])) { - $multi[$key] = array($out[$child->name]); - unset($out[$child->name]); - } - $multi[$key][] = $value; - } else { - $out[$child->name] = $value; + if (count($child->children) == 1) { + $leaf = true; } - continue; } elseif (count($child->children) === 0 && $child->value == '') { $value = $child->attributes; - if (isset($out[$key]) || isset($multi[$key])) { - if (!isset($multi[$key])) { - $multi[$key] = array($out[$key]); - //unset($out[$key]); - } - $multi[$key][] = $value; - } elseif (!empty($value)) { - $out[$key] = $value; - } else { - $out[$child->name] = $value; + if (empty($value)) { + $leaf = true; } - continue; } else { $value = $child->toArray($camelize); } - if (!isset($out[$key])) { - $out[$key] = $value; - } else { - if (!is_array($out[$key]) || !isset($out[$key][0])) { + if (isset($out[$key])) { + if(!isset($out[$key][0]) || !is_array($out[$key]) || !is_int(key($out[$key]))) { $out[$key] = array($out[$key]); - } + } $out[$key][] = $value; + } elseif (isset($out[$child->name])) { + $t = $out[$child->name]; + unset($out[$child->name]); + $out[$key] = array($t); + $out[$key][] = $value; + } elseif ($leaf) { + $out[$child->name] = $value; + } else { + $out[$key] = $value; } } - - if (isset($multi)) { - $out = array_merge($out, $multi); - } return $out; } /** @@ -1400,4 +1387,4 @@ function &getInstance() { return $instance[0]; } } -?> \ No newline at end of file +?> diff --git a/cake/tests/cases/libs/xml.test.php b/cake/tests/cases/libs/xml.test.php index 8eca83c8ded..8535ffd26b0 100644 --- a/cake/tests/cases/libs/xml.test.php +++ b/cake/tests/cases/libs/xml.test.php @@ -1390,5 +1390,195 @@ function testMemoryLeakInConstructor() { $end = memory_get_usage(); $this->assertWithinMargin($start, $end, 3600, 'Memory leaked %s'); } + +/** + * Test toArray with alternate inputs. + * + * @return void + */ + function testToArrayAlternate() { + $sXml = + ' + A + AAAB + C + '; + $xml = new Xml($sXml); + $result = $xml->toArray(); + $expected = array( + 'T1' => array( + 'T2' => array( + 'A', + array('t3' => 'AAA', 'value' => 'B'), + 'C' + ) + ) + ); + $this->assertIdentical($result, $expected); + $result = $xml->toArray(false); + $expected = array( + 't1' => array( + 't2' => array( + 'A', + array('t3' => 'AAA', 'value' => 'B'), + 'C' + ) + ) + ); + $this->assertIdentical($result, $expected); + + $sXml = + ' + A + B + + CCC + + '; + $xml = new Xml($sXml); + $result = $xml->toArray(); + $expected = array( + 'T1' => array( + 'T2' => array( + 'A', + 'B', + array('t3' => 'CCC'), + ) + ) + ); + $this->assertIdentical($result, $expected); + $result = $xml->toArray(false); + $expected = array( + 't1' => array( + 't2' => array( + 'A', + 'B', + array('t3' => 'CCC'), + ) + ) + ); + $this->assertIdentical($result, $expected); + + $sXml = + ' + A + + C + '; + $xml = new Xml($sXml); + $result = $xml->toArray(); + $expected = array( + 'T1' => array( + 'T2' => array( + 'A', + array(), + 'C' + ) + ) + ); + $this->assertIdentical($result, $expected); + + $result = $xml->toArray(false); + $expected = array( + 't1' => array( + 't2' => array( + 'A', + array(), + 'C' + ) + ) + ); + $this->assertIdentical($result, $expected); + + $sXml = + ' + + + + + + + + + + + + +'; + $xml = new Xml($sXml); + $result = $xml->toArray(); + $expected = array( + 'Stuff' => array( + 'Foo' => array( + array('name' => 'abc-16', 'profile-id' => 'Default'), + array('name' => 'abc-17', 'profile-id' => 'Default', + 'Bar' => array('id' => 'HelloWorld')), + array('name' => 'abc-asdf', 'profile-id' => 'Default'), + array('name' => 'cba-1A', 'profile-id' => 'Default', + 'Bar' => array('id' => 'Baz')), + array('name' => 'cba-2A', 'profile-id' => 'Default', + 'Bar' => array('id' => 'Baz')), + array('name' => 'qa', 'profile-id' => 'Default'), + ) + ) + ); + $this->assertIdentical($result, $expected); + $result = $xml->toArray(false); + $expected = array( + 'stuff' => array( + 'foo' => array( + array('name' => 'abc-16', 'profile-id' => 'Default'), + array('name' => 'abc-17', 'profile-id' => 'Default', + 'bar' => array('id' => 'HelloWorld')), + array('name' => 'abc-asdf', 'profile-id' => 'Default'), + array('name' => 'cba-1A', 'profile-id' => 'Default', + 'bar' => array('id' => 'Baz')), + array('name' => 'cba-2A', 'profile-id' => 'Default', + 'bar' => array('id' => 'Baz')), + array('name' => 'qa', 'profile-id' => 'Default'), + ) + ) + ); + $this->assertIdentical($result, $expected); + + + $sXml = + ' + + + +'; + $xml = new Xml($sXml); + $result = $xml->toArray(); + $expected = array( + 'Root' => array( + 'Node' => array( + array('name' => 'first'), + array('name' => 'second', + 'Subnode' => array( + array('name' => 'first sub'), + array('name' => 'second sub'))), + array('name' => 'third'), + ) + ) + ); + $this->assertIdentical($result, $expected); + + $result = $xml->toArray(false); + $expected = array( + 'root' => array( + 'node' => array( + array('name' => 'first'), + array('name' => 'second', + 'subnode' => array( + array('name' => 'first sub'), + array('name' => 'second sub'))), + array('name' => 'third'), + ) + ) + ); + $this->assertIdentical($result, $expected); + } + } -?> \ No newline at end of file +?>