More than three elements at same level causes an error
Status: Beta
Brought to you by:
psychogenic
I have the following XML:
---
<doc>
<section>
<para>
<heading>head1</heading>
</para>
<para>
<heading>head2</heading>
</para>
<para>
<heading>head3</heading>
</para>
<para>
<heading>head4</heading>
</para>
</section>
</doc>
---
Assuming this is available in the variable $xml, I
issue the following PHP in my script:
---
$parsedDoc = new MiniXMLDoc();
$parsedDoc->fromString($xml);
$ar = $parsedDoc->toArray();
echo "<pre>";
print_r($ar);
echo "</pre>";
---
Which wrongly returns the following array:
---
Array
(
[doc] => Array
(
[section] => Array
(
[para] => Array
(
[heading] => head4
)
)
)
)
---
Removin the fourth <para> element from the XML,
everything looks fine. What gives?
/geddeth
Logged In: YES
user_id=1076093
Hi - we ran into the same bug working on a shopping cart. I
spent the evening tracing and debugging and believe I have
the fix. I have not done extensive testing, but from what
I've tried it seems to work.
In the file element.inc.php, in the function toStructure(),
there is a line that reads "$existing = NULL;". I took this
initialization and moved it to just before the enclosing
loop and it seems to solve the problem and continue to
funtion otherwise.
OLD CODE:
for($i=0; $i< $this->xnumChildren; $i++)
{
if ($this->isElement($this->xchildren[$i]))
{
$name = $this->xchildren[$i]->name();
$struct = $this->xchildren[$i]->toStructure();
$existing = NULL; // <= Problem Line
if (isset($retHash[$name]))
=========================
NEW CODE:
$existing = NULL; // moved from below v
for($i=0; $i< $this->xnumChildren; $i++)
{
if ($this->isElement($this->xchildren[$i]))
{
$name = $this->xchildren[$i]->name();
$struct = $this->xchildren[$i]->toStructure();
//$existing = NULL; // Moved to before the loop ^
if (isset($retHash[$name]))
=========================
Hope this helps!
Logged In: YES
user_id=1159949
Hi,
I believe the fix suggested by gryphonsmoon is incorrect. I
was still able to hit a bug with that fix in place, with the
following XML:
<parent>
<child1>somevalue</child1>
<child1>anothervalue</child1>
<child1>yetanothervalue</child1>
<child2>something</child2>
<child2>somethingelse</child2>
<child2>anothersomething</child2>
</parent>
Basically, the resulting array had child2's values in the
child1 array.
The real bug is that the author has made the assumption that
assigning an empty array to an existing array variable will
"clear" that array. Unfortunately PHP4 doesn't work that
way -- you have to unset() the variable first.
I had cleaned up the toStructure() method before I realised
that this one-liner would fix the bug; my cleanup diff follows:
--- orig_element.inc.php 2004-11-16 12:28:05.000000000 +1100
+++ element.inc.php 2004-11-16 12:28:05.000000000 +1100
@@ -1237,25 +1237,20 @@
{
$name = $this->xchildren[$i]->name();
$struct = $this->xchildren[$i]->toStructure();
- $existing = NULL;
- if (isset($retHash[$name]))
- {
- $existing =& $retHash[$name];
- }
-
- if ($existing)
- {
- if (_MiniXML_NumKeyArray($existing))
- {
- array_push($existing, $struct);
+ if (isset($retHash[$name])) {
+ // A child element with this name has already been seen
+ if (_MiniXML_NumKeyArray($retHash[$name])) {
+ // The child element array was already a plain array, so
+ // we can just append this instance to it
+ array_push($retHash[$name], $struct);
} else {
- $newArray = array();
- array_push($newArray, $existing);
- array_push($newArray, $struct);
- $retHash[$name] =& $newArray;
+ // The child element array was associative, so in order
+ // to append this instance we need to convert it to a
plain array
+ $retHash[$name] = array($retHash[$name], $struct);
}
} else {
+ // We've not seen this child element before
$retHash[$name] = $struct;
}
$numAdded++;
Hope this helps!
Simon.