Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

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
@markstory markstory authored
Showing with 209 additions and 32 deletions.
  1. +18 −31 cake/libs/xml.php
  2. +191 −1 cake/tests/cases/libs/xml.test.php
View
49 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];
}
}
-?>
+?>
View
192 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 =
+ '<t1>
+ <t2>A</t2>
+ <t2><t3>AAA</t3>B</t2>
+ <t2>C</t2>
+ </t1>';
+ $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 =
+ '<t1>
+ <t2>A</t2>
+ <t2>B</t2>
+ <t2>
+ <t3>CCC</t3>
+ </t2>
+ </t1>';
+ $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 =
+ '<t1>
+ <t2>A</t2>
+ <t2></t2>
+ <t2>C</t2>
+ </t1>';
+ $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 =
+ '<stuff>
+ <foo name="abc-16" profile-id="Default" />
+ <foo name="abc-17" profile-id="Default" >
+ <bar id="HelloWorld" />
+ </foo>
+ <foo name="abc-asdf" profile-id="Default" />
+ <foo name="cba-1A" profile-id="Default">
+ <bar id="Baz" />
+ </foo>
+ <foo name="cba-2A" profile-id="Default">
+ <bar id="Baz" />
+ </foo>
+ <foo name="qa" profile-id="Default" />
+</stuff>';
+ $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 =
+ '<root>
+ <node name="first" />
+ <node name="second"><subnode name="first sub" /><subnode name="second sub" /></node>
+ <node name="third" />
+</root>';
+ $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);
+ }
+
}
-?>
+?>
Please sign in to comment.
Something went wrong with that request. Please try again.