Attempting to create a new column within an existing table using DOMDocument and DOMXpath
$doc = new DOMDocument();
$doc->loadHTMLFile("example.html");
Here is how the table located in example.html
is structured:
<table id="transactions" class="table">
<thead>
<tr>
<th class="image"></th>
<th class="title"><span>Title</span></th>
</tr>
</thead>
<tbody>
<tr id="tbody-tr">
<td class="image">
<img src="http://www.example.com/image.jpg">
</td>
<td class="title">Title
</td>
<td class="date">12/16/2017
</td>
</tr>
<tr id="tbody-tr">
<td class="image">
<img src="http://www.example.com/image.jpg">
</td>
<td class="title">Title
</td>
<td class="date">12/16/2017
</td>
</tr>
</tbody>
</table>
In this case, the xpath query for the table would be
$table = $xpath->query('//*[@id="transactions"]');
For the <tr id="tbody-tr">
element
$tr = $xpath->query('/*[@id="tbody-tr"]');
And for the <td>
row elements -- /td[1] /td[2] /td[3]
$td = $xpath->query('//*[@id="tbody-tr"]/td[3]');
I'm trying to create an additional column (<td class="example"></td>
) in between <td class="title">
and <td class="date">
for all instances of <tr id="tbody-tr">
(there are about 50, but minified for the sake of the question).
I'm new to DOMDocument and HTML Parsing Manipulation, and am having a hell of a time trying to figure out how to do this.
I'm assuming I'll either have to loop it using my xpath->query
, something like
foreach ($ttrows as $row) {
$td = $doc->createElement('td');
$parent = $row->parentNode;
$parent->appendChild($row);
$td->setAttribute('class','example');
}
or use DOMDocuments getElementById
or something similar.
foreach ($table = $doc->getElementById('tbody-tr') as $table) {
$td = $doc->createElement('td');
$td->setAttribute('class', 'example');
$td->appendChild($table);
$table->insertBefore($td, $table);
}
As I said, I am new to DOMDocument, so both of those examples do practically nothing.. but I think I am heading in the right direction (I hope).
The table, I believe, is fairly well structured to do something like this in DOMDocument. Can someone please shed some light on this, my trials and errors are leaving me with little result.
Solution:
foreach ($td as $row) {
$td = $doc->createElement('td', 'text to be inserted');
$td->setAttribute('class','example');
$row->parentNode->insertBefore($td, $row);
}
Note above that
$td = $xpath->query('//*[@id="tbody-tr"]/td[3]');
is the third <td>
class date
.
Remember you cant/shouldnt have multiple ids on the same page.
Then just use $tr->insertBefore($td, $tr->childNodes->item(3));
Which means, current node insert new dom node before 3rd td.
<?php
foreach ($doc->getElementsByTagName('tr') as $tr) {
$td = $doc->createElement('td');
$td->setAttribute('class', 'example');
$tr->insertBefore($td, $tr->childNodes->item(3));
}
Also something to think about is to add the thead > th
or it will break the look of table.
foreach ($doc->getElementsByTagName('tr') as $tr) {
// insert into thead > th
if ($tr->childNodes->item(0)->nodeName == 'th') {
$th = $doc->createElement('th');
$th->setAttribute('class', 'example');
$th->nodeValue = 'Example';
$tr->insertBefore($th, $tr->childNodes->item(3));
}
// insert into body > td
else {
$td = $doc->createElement('td');
$td->setAttribute('class', 'example');
$tr->insertBefore($td, $tr->childNodes->item(3));
}
}