The online racing simulator
PHP nested array referencing... issues!
(9 posts, started )
PHP nested array referencing... issues!
Bleh... I know we've got some PHP monkeys in here, throw me a bone...

I'm trying to parse an XML document (with no attributes - just plain tagnames and cdata) into a nested array, so I can preserve the data structure, so the result would be something like...


$arr
[tagname]
[0]
[tagname]
[var]=<val>
[1]
[tagname]
[var]=<val>

etc.

That sort of thing. A quick start seemed to be to use xml_parse_into_struct(), then I figured I'd loop through that array and build my hierarchy, but I'm having an issue trying to record my current position in the array I'm building, or - more correctly - referencing that position successfully to do the assignment when I come across a cdata value that I want to store.

I'm using a stack, $pos, and each time I come across an open tag I push the tagname onto that stack, and each time I find a closing tag I pop it off. So at any given time I've got a stack something like:


$pos
[0]='tagname'
[1]='0'
[2]='var'

And I want to concatenate those elements into a usable array reference, $arr[tagname][0][var], to do the assignment.

I've tried concatting the lot into a string and using that string as a variable variable, but that doesn't work. It's 2am and my mind is blank - any suggestions?
#2 - wien
Not a solution to your problem as such, but wouldn't it be easier to use a DOM parser if you need to keep the hierarchy? There's one built into PHP5 if I'm not mistaken.

EDIT: Reading once more I'm still not sure I understand what you want to do. Could you add a short snippet of example XML and what the resulting array should look like perhaps?
Quote from wien :Not a solution to your problem as such, but wouldn't it be easier to use a DOM parser if you need to keep the hierarchy? There's one built into PHP5 if I'm not mistaken.

Thing is, it's a remote script intended to run one of our customers' online stores on third-party websites. So I want to keep the requirements simple in terms of what's built into PHP and how heavy it is on the CPU (I don't have time or budget to build in cacheing, and that would only complicate the remote install anyway - it really needs to just unzip and run)

Quote from wien : EDIT: Reading once more I'm still not sure I understand what you want to do. Could you add a short snippet of example XML and what the resulting array should look like perhaps?

I need a system that doesn't care what the XML consists of (so we can update the feed without worrying about whether clients will choke on it). Basically what I'm aiming for is:


XML:
<?xml version="1.0"?>
<group>
<page>
<id>page1</id>
<title>Page 1</title>
</page>
<page>
<id>page2</id>
<title>Page 2</title>
</page>
</group>

Into:


$arr = array(
[group] => array(
[0] => array(
[page] => array(
[0] => array(
[id]=>"page1"
[title]=>"Page 1"
[1] => array(
[id]=>"page2"
[title]=>"Page 2"
)
)
)
)
);

Meh... I'm too tired to explain where I got stuck. It's 5:15am!!! I am totally going to bed!

FTR: The reason I want that structure in the array is so I can throw it straight at our template system - which loves arrays like that.
#4 - wien
Quote from thisnameistaken :I've tried concatting the lot into a string and using that string as a variable variable, but that doesn't work. It's 2am and my mind is blank - any suggestions?

Oooooh! I just got the problem. It was time for bed for me as well I think. Something like this then? The function assumes $arr is an array, that $path contains the stack you described, and that $value is the cdata you want that node to have.

<?php 
funtion assignToHierarchy
(&$arr$path$value)
{
    
$current &= $arr;
    foreach(
$path as $node)
    {
       if(!
array_key_exists($node$current))
            
$current[$node] = array();

        
$current &= $current[$node];
    }

    
$current $value;
}
?>

I'm sure there's more elegant ways of doing this, but it should work.
Quote from wien :Oooooh! I just got the problem. It was time for bed for me as well I think. Something like this then?

Hi dude, thanks for your help while I got some much-needed sleep! I've just got out of bed and I'm still trying to get enough coffee inside me to be able to function, then I'll take a proper look at this. It does look like the sort of approach I should've used, instead of trying to hack the array index together as a string... :dunce:
#6 - wien
Quote from thisnameistaken :It does look like the sort of approach I should've used, instead of trying to hack the array index together as a string... :dunce:

Heh, you could do that as well I guess. By building actual PHP code and using the evil, evil eval function...

Hope it works out though.
#7 - Ian.H
Quote from wien :Heh, you could do that as well I guess. By building actual PHP code and using the evil, evil eval function...

Hope it works out though.

Heh.. "if eval() is the answer, you're asking the wrong question"



Regards,

Ian
Quote from Ian.H :Heh.. "if eval() is the answer, you're asking the wrong question"

YA RLY.

Here's a working version of wien's function on the rare off-chance that anybody else ever needs it. I switched it to use isset() because of issues with array_key_exists() in some versions of PHP, which is fine for me because I'm never using NULL values.


function assignToHierarchy(&$arr, $path, $value) {
$current =& $arr;
foreach($path as $node) {
if(!isset($current[$node])) {
$current[$node] = array();
}
$current =& $current[$node];
}
$current = $value;
}

Thanks again, you've been very helpful. I never use assignments by reference, so I never would've come up with this solution.
#9 - wien
Quote from thisnameistaken :Thanks again, you've been very helpful. I never use assignments by reference, so I never would've come up with this solution.

Me neither as you can see by me typing the operator the wrong way around. I'm just too used to C++ and pointers, and thought along those lines. Glad it worked out though.

PHP nested array referencing... issues!
(9 posts, started )
FGED GREDG RDFGDR GSFDG