views:

51

answers:

2

Hi, php newbie here..I need some PHP help ideas/examples on how to import data from a delimited text file and map them into html tables. The data should populate and be mapped under its proper header. There are instances also where each record doesn't have all the values and if no data, then we can leave it null (See sample records). I would also create a table row entry for each record.

For example, the input/source file has these entries: (they are prefixed by a number to represent the header in the html table. So data from "1-MyServer" is "server4.mra.dev.pp1" and should be under table header "Server" for example. There are instances also where the record doesn't have all the values (1-7) (See below):

1-MyServer=server4.mra.dev.pp1;2-MyLogdate=Wed Aug 11 2010;3-MyDataset=dbip.pp1;4-MyStartTime=01:00:03;5-MyDuration=00:36:09;6-MySize=41.54 GB;7-MyStatus=Succeeded;
1-MyServer=server9.mra.dev.kul;2-MyLogdate=Wed Aug 11 2010;3-MyDataset=gls202.kul_lvm;5-MyDuration=06:20:33;7-MyStatus=Succeeded;
1-MyServer=server9.mra.dev.kul;2-MyLogdate=Wed Aug 11 2010;3-MyDataset=gls101.aie_lvm;4-MyStartTime=01:00:02;

Here is a copy of my html table that I would need it to map it too: (Also, I would not have to populate record for "2-MyLogdate" into a header)

<table id="stats">
tr>
  <th>Server</th>
  <th>Set</th>
  <th>Start</th>
  <th>Duration</th>
  <th>Size</th>
  <th>Status</th>
</tr>
<tr>
<td>server4.mel.dev.sp1</td>
<td>dbip.sp1</td>
<td>01:00:03</td>
<td>00:36:09</td>
<td>41.54 GB</td>
<td>Succeeded</td>
</tr>
</table>

So what I really need is a system to map these appropriately. How would I write this in php?? Thanks!

A: 

something like this

$logarr = file("log.txt");
foreach ($logarr as $s) {
  $s = str_replace(";","&",$s);
  $a = array();
  parse_str($s,$a);
  echo "<tr>\n";
  if (isset($a['1-MyServer'])) echo $a['1-MyServer']; else echo "&nbsp;"
  if (isset($a['2-MyLogdate'])) echo $a['2-MyLogdate']; else echo "&nbsp;"
  // and so on
  echo "</tr>\n";
}
Col. Shrapnel
I wouldn't use `parse_str` for something that's really really not GET or POST data.
zneak
so, you are free to use something else. there are always more than one way to do it. I prefer a shorter one :-P
Col. Shrapnel
zneak
@Col Shrapnel - thanks for your reply. I don't need to extract 2-MyLogdate, but yes to the rest of the attributes if they exist. So, if no values for '5-MyDuration' and '6-MySize' then leave the cell null/blank is fine.
jda6one9
@jaedre619 the problem is there can be no '5-MyDuration' but '4-MyDuration'. But I hope you've got enough ideas/examples to finish it yourself
Col. Shrapnel
@Col Shrapnel - no, each number is unique per attribute. I don't see a '4-MyDuration' its '4-MyStartTime' and '5-MyDuration'. Sorry for the confusion.
jda6one9
@jaedre619 ah yes. Well it's all set then.
Col. Shrapnel
+1  A: 

It's all about finding the patterns in your files. In your example, it's rather easy:

[number]-[column name]=[value];

The main problem I see is that you have redundant information: the number of the column, and the columns themselves, which are repeated for every row. You can parse them away, though. It depends on what you expect from your program: will the columns order always be the same? Will there always be the same columns? How should you react to unknown columns?

Here's a quick example of what you could do, using regular expressions. This example assumes that column names are all the same, and that you want to display them all, and that they'll always be in the same order. In other words, I'm doing it the easy way.

$data = array();

$lines = file("my/log/file.log");
// this will parse every line into an associative array, discarding the header number
foreach ($lines as $line)
{
    // populate $matches with arrays where indices are as follows:
    // 0: the whole string (0-Foo=bar;)
    // 1: the column number (0)
    // 2: the column name (Foo)
    // 3: the value (Bar)
    preg_match_all("/([0-9])-([^=]+)=([^;]+);/", $line, $matches, PREG_SET_ORDER);
    $lineData = array();
    foreach ($matches as $information)
        $lineData[$information[2]] = $information[3];
    $data[] = $lineData;
}

$keys = array_keys($data[0]); // you can also set this yourself
// for instance, $keys = array('MyServer', 'MyDataset'); would only display those two columns
echo '<table><tr>';
foreach ($keys as $column)
    echo '<th>' . $column . '</th>';
echo '</tr>';

foreach ($data as $row)
{
    echo '<tr>';
    foreach ($keys as $column)
        echo '<td>' . (isset($row[$column]) ? $row[$column] : '') . '</td>';
    echo '</tr>';
}
echo '</table>';
zneak
@zneak - thanks for your input. Yes, the columns of the table will remain the same. I just need to drop the value in. Some of the cols will not have data for that record, and we can leave it blank.
jda6one9
@jaedre619: this should pretty much work out of the box then.
zneak
@jaedre619 thought you were asking for some ideas/examples, not "Where to drop this code"...
Col. Shrapnel
@zneak- Thank you! This is great. It works fine out of the box. Just working now on how to get the css stuff working with it.
jda6one9
@jaedre619 what have you learned? When one learns something, they can do it again by themselves. will you write a regexp to parse another log format? or a loop? It seems you were looking for someone who will do a free job for you
Col. Shrapnel
@jaedre619 nobody is asking for your appreciation. And don't call it help. Help is when someone doing something and others come to help. But what was your part here? Pasted a code below body tag? Don't call it help. It's free job.
Col. Shrapnel