1

I have a script that curls a webpage and pulls out a table. I have gotten it to the point where

echo "<table>";
echo $table;
echo "</table>;

will output the table I am looking for, but what I need is for it to be in an array, so I can look at every row individually. The first row of the table has the column names, if that makes things any easier. Below is the format of the table:

<pre>
  <table>
    <tbody id="sortable1">
      <tr id="skip_coloring" class="nosort">
      <tr>
        <td class="border_even" style="white-space:nowrap">06/20/2011 4:33 PM </td>
        <td class="border_even">
          <strong>user_name, ext</strong>
        </td>
        <td class="border_even"> outside_num </td>
        <td class="border_even"> outgoing </td>
        <td class="border_even"> 12m, 14s </td>
        <td class="border_even"> 12m, 5s </td>
      <tr>
      <tr>
    </tbody>
  </table>
</pre>

id=skip_coloring has the column names. All other rows are data. Im using preg_match to get the table; if there is a better way to do it, let me know. Right now, I am using the following preg_match to get this table:

preg_match('#<table[^>]*id="row1"[^>]*>(.+?)<\\/table>#is', $cres_data, $matches);

but $matches is an array with 2 indexes, one for each page of results that the table creates. Maybe it would be better to try and match against each row within the table? I seem to recall that this could be done with simplexml or something, but I haven't gotten there yet. Any help is appreciated.

edit

Ended up using DOM; here's what I've got now:

$dom = new DomDocument();
$dom->loadHTML($cres_data);
$xpath = new DOMXPath($dom);

//get the first row of values
$arr = array();
foreach ($xpath->query('//tbody[@id="sortable1"]/tr/td') as $node)
        {
        $arr[] = $node->nodeValue;
        }
echo '<pre>';
print_($arr);

The output, however, isn't quite right:

Array
    (
    [0] => 

          Call Date 
    [1] => 

          Call From

.
.
.
    [7] => 







     06/20/2011  4:33 PM






    [8] => 







     user_name <ext>

Is there some way to remove all the whitespace, and get the column names as index labels? I assume I'd need to do this twice, or embed an additional foreach...it will always be formatted the same, if that matters.

edit

Used this function on both the labels and data to properly format it:

$label_arr =  array_filter(array_map('trim',$label_arr));

Output was exactly what I need.

Array
(
    [Call Date] =>  06/20/2011  4:33 PM
    [Call From] =>  user_name <ext>
    [Call To] =>  outside_num
    [Call Type] =>  outgoing
    [Call Time] =>  12m, 14s
    [Talk Time] =>  12m, 5s
)
1
  • As everyone will tell you don't try to parse HTML using regex. HTML is not a regular language. Trying to use regex to parse might work at first glance but will most definitively bite you in the ass later :) Commented Jun 29, 2011 at 16:23

5 Answers 5

2

You're better off with DomDocument's loadHTML and DomXPath. I believe this will do the trick, but it is untested:

$dom = new DomDocument();
$dom->loadHTML( $your_table );
$xpath = new DOMXPath( $dom );

$arr = array();
foreach ($xpath->query('//td') as $node) {
    $arr[] = $node->nodeValue;
}
Sign up to request clarification or add additional context in comments.

4 Comments

in the loadHTML bit, how do I include the table, when I havent segrated it from the page I took it from yet? I'm going though the dom manual now..
I believe all you'd have to do is change the xpath to: '//tbody[id="sortable1"]td', but I don't recall at the moment.
I cant seem to get it to do much but place the entire array into a single index; I've tried creating an additional foreach() below the original query to get the rows, but it doesn't like that $node is already an object. Would a query similar to '//div[@id="main1"]/tr' show me rows?
ohh, just found an excellent description of the query function. I will report back with better findings.
1

What you should do is parse this HTML with a DOM parser instead of regex. It will save you a lot of headache.

See How do you parse and process HTML/XML in PHP?

Comments

0

You need to use some DomDocument functions.

Don't use a regex.

Comments

0

I would use Dom Document to parse the html rather than regexp.

Comments

0

Apart From DOM Document as everyone suggested, you can use custom functions like "explode" to parse the pages, if the structure of the pages will remain the same.

SO, lets say $html = "HTML COntent";

$tables = explode("<table>", $html);

$table = $tables[1]; //Part after <table>

$table = explode("</table>", $table);
$table = $table[0]; //Part before </table>, so $table contains your table.

and then

$rows = explode("<tr>", $table);

// $rows[0] = to be neglected, it contains the part before the first <tr>
// $rows[1] = First TR, so your Heading row
//$rows[1-n] = Your data rows.

so

for ($i=2; $i<count($rows);$i++){
//process each row Here
}

1 Comment

Thanks, I think I will use the DOM method. It's very clean!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.