views:

71

answers:

2

Ok, so I tried searching around first but I didn't exactly know how to word this question or a search phrase. Let me explain.

I have data that looks like this:

<!-- data:start -->
    <!-- 0:start -->
        <!-- 0:start -->0,9<!-- 0:stop -->
        <!-- 1:start -->0,0<!-- 1:stop -->
        <!-- 2:start -->9,0<!-- 2:stop -->
        <!-- 3:start -->9,9<!-- 3:stop -->
        <!-- 4:start -->0,9<!-- 4:stop -->
    <!-- 0:stop -->
    <!-- 1:start -->
        <!-- 0:start -->1,5<!-- 0:stop -->
        <!-- 1:start -->1,6<!-- 1:stop -->
        <!-- 2:start -->3,6<!-- 2:stop -->
        <!-- 3:start -->3,8<!-- 3:stop -->
        <!-- 4:start -->4,8<!-- 4:stop -->
    <!-- 1:stop -->
    <!-- 2:start -->
        <!-- 0:start -->0,7<!-- 0:stop -->
        <!-- 1:start -->1,7<!-- 1:stop -->
    <!-- 2:stop -->
<!-- data:stop -->

So it's basically a bunch of points. Here is the code I'm currently using to try and parse it so that it would create an array like so:

Array (
    0 => Array (
        0 => "0,9",
        1 => "0,0",
        2 => "9,0",
        3 => "9,9",
        4 => "0,9"
    ),
    1 => Array (
        0 => "1,5",
        1 => "1,6",
        2 => "3,6",
        3 => "3,8",
        4 => "4,8"
    ),
    2 => Array (
        0 => "0,7",
        1 => "1,7"
    )
)

However, it is returning an array that looks like this:

Array (
    0 => "0,9",
    1 => "0,0",
    2 => "9,0"
)

Viewing the larger array that I have on my screen, you see that it's setting the first instance of that variable when matching. So how do I get it to find the widest match first and then process the insides. Here is the function I am currently using:

function explosion($text) {
    $number = preg_match_all("/(<!-- ([\w]+):start -->)\n?(.*?)\n?(<!-- \\2:stop -->)/s", $text, $matches, PREG_SET_ORDER);
    if ($number == 0) return $text;
    else unset($item);
    foreach ($matches as $item) if (empty($data[$item[2]])) $data[$item[2]] = $this->explosion($item[3]);
    return $data;
}

I'm sure it will be something stupid and simple that I've overlooked, but that just makes it an easy answer for you I suppose.

EDIT: Here is a full output log of the entire data set that I took this sample from. The tags are printed out (replace them with > and <) and it's all inside a giant <code></code> element for easy reading.

Here is the part that's messing up:

Array ( [0] => <!-- 0:start --> <!-- 0:start -->0,9<!-- 0:stop -->  [1] => 0 [2] => <!-- 0:start -->0,9 )

0 => <!-- 0:start -->0,9

So it's stopping at the first occurrence of the stop tag for another piece inside of it. Should I be thinking the opposite direction and processing the smallest pieces first, replacing those so it won't interrupt the larger pieces, and then processing the larger pieces?

+2  A: 

Here you go:

function explosion($text) {
    preg_match_all("/<!-- ([\d]+):start -->(.+?)<!-- .*:stop -->/", $text, $matches, PREG_SET_ORDER);

    $return = array();
    foreach($matches as $match) {
        if($match[1]==0) {
            $return[] = array();
        }
        $return[count($return)-1][] = $match[2];
    }   
    return $return;
}
celalo
+1 this works for me as well.
pinaki
I don't understand how this would work in a larger model? Wouldn't that only catch the array if it matched a 0 inside the tag? I added a log to the question, maybe it will help.
animuson
The idea is that you don't bother matching the outer tags, just the inner ones. Whenever the number in the start tag is `0`, you know the outer tag must have changed, so you create another array for the next batch of results.
Alan Moore
Ahh, I see now. Very nice.
animuson
+1  A: 

Well this works for me:

function explosion($text) {
    $number = preg_match_all('/<(.*?)>(.+?)[<]/s', $text, $matches);
    if ($number == 0) return $text;

    $temp = array();
    $data = array();
    foreach($matches[2] as $coords){
        if(trim($coords)==""){
            if(!empty($temp)){
                $data[] = $temp;
                $temp = array();
            }
        }else{
            $temp[] = $coords;
        }
    }
    return $data;
}

The problem with your code was that it was picking up the subtags and the tagged values. Of course it would be hidden when printed in browser, so try taking a log of it for debugging purpose.

pinaki