Applying patch from 'Stefano Rosanelli' which fixes Xml::toArray() greatly improving

its ability to convert xml documents.  Fixes #1667
This commit is contained in:
mark_story 2011-04-21 22:38:41 -04:00
parent 3a7f44e04c
commit 9914258807
2 changed files with 207 additions and 30 deletions

View file

@ -687,11 +687,11 @@ class XmlNode extends Object {
*/
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;
@ -700,47 +700,34 @@ class XmlNode extends Object {
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;
}

View file

@ -1434,4 +1434,194 @@ class XmlTest extends CakeTestCase {
$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);
}
}