Skip to content

Commit

Permalink
Applying patch from 'Stefano Rosanelli' which fixes Xml::toArray() gr…
Browse files Browse the repository at this point in the history
…eatly improving

its ability to convert xml documents.  Fixes #1667
  • Loading branch information
markstory committed Apr 22, 2011
1 parent 3a7f44e commit 9914258
Show file tree
Hide file tree
Showing 2 changed files with 207 additions and 30 deletions.
47 changes: 17 additions & 30 deletions cake/libs/xml.php
Expand Up @@ -687,11 +687,11 @@ function toString($options = array(), $depth = 0) {
*/ */
function toArray($camelize = true) { function toArray($camelize = true) {
$out = $this->attributes; $out = $this->attributes;
$multi = null;


foreach ($this->children as $child) { foreach ($this->children as $child) {
$key = $camelize ? Inflector::camelize($child->name) : $child->name; $key = $camelize ? Inflector::camelize($child->name) : $child->name;


$leaf = false;
if (is_a($child, 'XmlTextNode')) { if (is_a($child, 'XmlTextNode')) {
$out['value'] = $child->value; $out['value'] = $child->value;
continue; continue;
Expand All @@ -700,47 +700,34 @@ function toArray($camelize = true) {
if ($child->attributes) { if ($child->attributes) {
$value = array_merge(array('value' => $value), $child->attributes); $value = array_merge(array('value' => $value), $child->attributes);
} }
if (isset($out[$child->name]) || isset($multi[$key])) { if (count($child->children) == 1) {
if (!isset($multi[$key])) { $leaf = true;
$multi[$key] = array($out[$child->name]);
unset($out[$child->name]);
}
$multi[$key][] = $value;
} else {
$out[$child->name] = $value;
} }
continue;
} elseif (count($child->children) === 0 && $child->value == '') { } elseif (count($child->children) === 0 && $child->value == '') {
$value = $child->attributes; $value = $child->attributes;
if (isset($out[$key]) || isset($multi[$key])) { if (empty($value)) {
if (!isset($multi[$key])) { $leaf = true;
$multi[$key] = array($out[$key]);
//unset($out[$key]);
}
$multi[$key][] = $value;
} elseif (!empty($value)) {
$out[$key] = $value;
} else {
$out[$child->name] = $value;
} }
continue;
} else { } else {
$value = $child->toArray($camelize); $value = $child->toArray($camelize);
} }


if (!isset($out[$key])) { if (isset($out[$key])) {
$out[$key] = $value; if(!isset($out[$key][0]) || !is_array($out[$key]) || !is_int(key($out[$key]))) {
} else {
if (!is_array($out[$key]) || !isset($out[$key][0])) {
$out[$key] = array($out[$key]); $out[$key] = array($out[$key]);
} }
$out[$key][] = $value; $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; return $out;
} }


Expand Down
190 changes: 190 additions & 0 deletions cake/tests/cases/libs/xml.test.php
Expand Up @@ -1434,4 +1434,194 @@ function testMemoryLeakInConstructor() {
$end = memory_get_usage(); $end = memory_get_usage();
$this->assertWithinMargin($start, $end, 3600, 'Memory leaked %s'); $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);
}

} }

0 comments on commit 9914258

Please sign in to comment.