Extract string using #, | and % delimiters into a HTML table using PHP

Viewed 64

I have a variable with delimiters. I have three countries CountryA, CountryB & CountryC. The first delimiter is the # which specifies the start and end of the Country name. The second delimiter is the | pipe. So under each country, we there is a set of data separated individually by the pipe. The third delimiter is the % which specifies the end of each set of data above.

$sample="CountryA#Test1|101|Test2|%Test0|220|Test3|%#CountryB#Test4|103|Test5|%
Test6|400|Test7|%Test8|500|Test9|%#CountryC#TestA|230|TestB|%";

The above variable organized looks like this:

CountryA#
         Test1|101|Test2|%
         Test0|220|Test3|%
#CountryB#
         Test4|103|Test5|%
         Test6|400|Test7|%
         Test8|500|Test9|%
#CountryC#
         TestA|230|TestB|%

The delimiters #,| and % help identify where each data starts and ends. In the country, the first element does not have a starting # because it's not important. The subsequent countries have a starting and closing # to help identify where the country name is.

Objective:

Output - Image

I tried using explode # to first get the country names before wrapping them inside html tags but nothing happens.

$pieces = explode("#", $sample);
foreach($pieces as $value){
    return $value . '<br>';
}
1 Answers

The reason why nothing happens with your code is because you're using return, which is used by functions to return a result, while I assume you wanted to use echo to print the $value. So the first thing to note is that your initial code would output something if you correctly use echo.

Nevertheless, due to the complexity of the type of string you're trying to parse, exploding by # might not be the best choice, as you would have the country name separated from its child nodes.

I would suggest instead to use preg_match_all to divide the initial $sample into pieces, each containing all the info of a single country.

Like this:

preg_match_all('@[A-z]+\#[^\#]+@', $sample, $countries);

This would return in $countries[0] an array containing 3 elements, each with all the data of each country. For example the first array would contain

CountryA#Test1|101|Test2|%Test0|220|Test3|%

Once you have this array, you can then explode first by %, then by | to obtain the remaining elements.

The full code to parse is

preg_match_all('@[A-z]+\#[^\#]+@', $sample, $countries);
$results = [];
foreach ($countries[0] as $c) {
    $c = explode("#", $c);
    $country_name = $c[0];
    $results[$country_name] = [];
    $params = explode("%", $c[1]);
    foreach ($params as $param_line) {
        if (!$param_line) {
            continue;
        }
        $results[$country_name][] = explode("|", trim($param_line, '|'));
    }
}

The $results array contains a multi-dimentional array with all the info divided by country and attributes, like this:

array(3) {
  ["CountryA"]=>
  array(2) {
    [0]=>
    array(3) {
      [0]=>
      string(5) "Test1"
      [1]=>
      string(3) "101"
      [2]=>
      string(5) "Test2"
    }
    [1]=>
    array(3) {
      [0]=>
      string(5) "Test0"
      [1]=>
      string(3) "220"
      [2]=>
      string(5) "Test3"
    }
  }
  ["CountryB"]=>
  array(3) {
    [0]=>
    array(3) {
      [0]=>
      string(5) "Test4"
      [1]=>
      string(3) "103"
      [2]=>
      string(5) "Test5"
    }

Finally, if you want to translate this array into an HTML table similar to the one you show in your example, you can simply loop the $results array by 3 levels and print the results. Here's a sample

<table width="500">
<?php
foreach ($results as $country_name => $params) {
    ?>
    <tr><th colspan="3" style="text-align:center"><?=$country_name ?></th></tr>
    <?php foreach ($params as $param_line) {?>
    <tr>
        <td width="33%" style="text-align: center;"><?=$param_line[0] ?></td>
        <td width="33%" style="text-align: center;"><?=$param_line[1] ?></td>
        <td width="33%" style="text-align: center;"><?=$param_line[2] ?></td>
    </tr>
    <?php }?>
<?php } ?>
</table>

Which will output this:

enter image description here

Related