2

So my previous question: PHP Convert html table to JSON was quickly dismissed as a duplicate and I'm still struggling to get to what I need. I think it's mostly a logic problem in the loops and I need someone else to take a look at it.

Given this table as an example:

<table id="Details" class="DATA_TABLE DATA_TABLE_WO_TOTAL">
  <tr>
    <th>Application</th>
    <th>Version number</th>
    <th>Virtual Administration Server</th>
    <th>Group</th>
    <th>Device</th>
    <th>Installed</th>
    <th>Last visible time</th>
    <th>Last connection to Administration Server</th>
    <th>IP address</th>
  </tr>
  <tr>
    <td class="sD">some text</td>
    <td class="sD">10.2.5.3201</td>
    <td class="sD"></td>
    <td class="sD">Thin PC</td>
    <td class="sD">PC#</td>
    <td class="sD">date</td>
    <td class="sD">date</td>
    <td class="sD">date</td>
    <td class="sD">ip address</td>
  </tr>
  <tr>
     <tr>
    <td class="sD">some more text</td>
    <td class="sD">10.2.5.3201</td>
    <td class="sD"></td>
    <td class="sD">Thin PC</td>
    <td class="sD">PC#</td>
    <td class="sD">date</td>
    <td class="sD">date</td>
    <td class="sD">date</td>
    <td class="sD">ip address</td>
  </tr>
</table>

I need to create an array (that I can later convert to a json) where the th tags are the keys and then all the td tags inside each other tr is the data corresponding to these keys. I have the following php code:

<?php
$dom = new DOMDocument;
$dom->loadHTML($cleantable2); //this is the table above
$xpath = new DOMXPath($dom);

foreach($xpath->query('//table/tr') as $tr){
        $tmp = [];
                foreach($xpath->query('//table/tr/th', $tr) as $th){
                        $key = $th->textContent;
                        foreach($xpath->query('td', $tr) as $td){
                                $tmp[$key] = trim($td->textContent);
                        }
                }
                $result[]=$tmp;
        }
var_dump($result);

?>

It does get the keys right, but not the data, sample output:

  [89]=>
  array(9) {
    ["Application"]=>
    string(13) "192.168.6.104"
    ["Version number"]=>
    string(13) "192.168.6.104"
    ["Virtual Administration Server"]=>
    string(13) "192.168.6.104"
    ["Group"]=>
    string(13) "192.168.6.104"
    ["Device"]=>
    string(13) "192.168.6.104"
    ["Installed"]=>
    string(13) "192.168.6.104"
    ["Last visible time"]=>
    string(13) "192.168.6.104"
    ["Last connection to Administration Server"]=>
    string(13) "192.168.6.104"
    ["IP address"]=>
    string(13) "192.168.6.104"
  }

As you can see, it only picks up the IP address for each key and not the rest of the data. What am I doing wrong? Can someone help out and not just dismiss this as a duplicate? Been trying to figure this out for over a day, I'm pretty sure my issue is just not looping correctly but I'm not seeing it...

Thanks

1 Answer 1

2
$strhtml='
<table id="Details" class="DATA_TABLE DATA_TABLE_WO_TOTAL">
  <tr>
    <th>Application</th>
    <th>Version number</th>
    <th>Virtual Administration Server</th>
    <th>Group</th>
    <th>Device</th>
    <th>Installed</th>
    <th>Last visible time</th>
    <th>Last connection to Administration Server</th>
    <th>IP address</th>
  </tr>
  <tr>
    <td class="sD">some text</td>
    <td class="sD">10.2.5.202</td>
    <td class="sD">Plato</td>
    <td class="sD">Thin PC</td>
    <td class="sD">PC#</td>
    <td class="sD">date a</td>
    <td class="sD">date b</td>
    <td class="sD">date c</td>
    <td class="sD">10.25.100.1</td>
  </tr>
  <tr>
     <tr>
    <td class="sD">some more text</td>
    <td class="sD">10.2.5.321</td>
    <td class="sD">Socrates</td>
    <td class="sD">Thick PC</td>
    <td class="sD">PC#</td>
    <td class="sD">date x</td>
    <td class="sD">date y</td>
    <td class="sD">date z</td>
    <td class="sD">10.25.100.2</td>
  </tr>
</table>';

Given the above html snippet perhaps the following does what you need? The comments should help see what I have done

libxml_use_internal_errors( true );
$dom=new DOMDocument;
$dom->loadHTML( $strhtml );
libxml_clear_errors();

$xp=new DOMXPath( $dom );
/* find the `th` elements */
$col = $xp->query( '//tr/th' );

/* temp arrays */
$tmp=$out=$keys=array();


if( $col->length > 0 ){
    /* get all headers as keys */
    foreach( $col as $node )$keys[]=$node->nodeValue;

    /* get all table cell data - store in single array */
    $col=$xp->query( '//tr/td[ @class="sD" ]' );
    foreach( $col as $node )$tmp[]=$node->nodeValue;

    /* split data into chunks according to number of columns */
    $rows=array_chunk( $tmp, count( $keys ) );

    /* combine keys and chunks */
    foreach( $rows as $row ){
        $tmp=array();
        foreach( $row as $i => $value ) $tmp[ $keys[ $i ] ]=$value;
        $out[]=$tmp;
    }

    echo json_encode( $out );
}

output:

[
    {
        "Application":"some text",
        "Version number":"10.2.5.202",
        "Virtual Administration Server":"Plato",
        "Group":"Thin PC",
        "Device":"PC#",
        "Installed":"date a",
        "Last visible time":"date b",
        "Last connection to Administration Server":"date c",
        "IP address":"10.25.100.1"
    },
    {
        "Application":"some more text",
        "Version number":"10.2.5.321",
        "Virtual Administration Server":"Socrates",
        "Group":"Thick PC","Device":"PC#",
        "Installed":"date x",
        "Last visible time":"date y",
        "Last connection to Administration Server":"date z",
        "IP address":"10.25.100.2"
    }
]
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks so much, exactly what I needed it to do!!

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.