I am using PHP HTML DOM Parser to traverse a table DOM on a third party site and print out a particular set of values in a td element.
<?php foreach($html->find('td#column2.style3') as $e) { $sponsor3 = $e->parent()->next_sibling()->next_sibling()->next_sibling()->children(4)->plaintext; echo "Sponsor3 <strong>" . $sponsor3 . "</strong><br>"; } ?>
This works for the first two columns I traverse.
However, in the 3rd column, the $e operation returns Null. The HTML for that element is:
<td style="" id="column5" valign="top" class="style3"></td>
The problem I have, is that it throws a Fatal Error on this element and so the rest of the script won’t run.
The line throwing the error is:
$sponsor3 = $e->parent()->next_sibling()->next_sibling()->next_sibling()->children(4)->plaintext;
Fatal error: Uncaught Error: Call to a member function children() on null
I need to be able to traverse even if the call is null… What can I do so as not to break the script if one of the column elements is null?
Here is the HTML that I am scraping:
<tbody style="page-break-inside: avoid"> <tr> <td style="" id="column1" valign="top"></td> <td style="" id="column2" valign="top" class="style3">R5</td> <td style="" id="column3" valign="top" class="style2">A</td> <td style="" id="column4" valign="top" colspan="2" class="style2"> <a target="_blank" href="CoverSheet.aspx?ItemID=19186&MeetingID=779"> <p>AN ORDINANCE OF THE MAYOR AND CITY COMMISSION OF THE CITY OF MIAMI BEACH, FLORIDA, AMENDING CHAPTER 30 OF THE MIAMI BEACH CITY CODE, ENTITLED "CODE ENFORCEMENT," BY AMENDING ARTICLE Il, ENTITLED "SPECIAL MASTER," BY AMENDING SECTION 30-37, ENTITLED "TERMS OF OFFICE; COMPENSATION"; BY AMENDING THE COMPENSATION OF THE SPECIAL MASTER(S); PROVIDING FOR CODIFICATION, REPEALER, SEVERABILITY, AND AN EFFECTIVE DATE.</p> </a> </td> <td style="" id="column6" valign="top"></td> <td style="" id="column7" valign="top"></td> <td style="" id="column8" valign="top"></td> </tr> <tr> <td style="" id="column1" valign="top"></td> <td style="" id="column2" valign="top"></td> <td style="" id="column3" valign="top"></td> <td style="" id="column4" valign="top"></td> <td style="" id="column5" valign="top"></td> <td style="" id="column6" valign="top"></td> <td style="" id="column7" valign="top"></td> <td style="" id="column8" valign="top"></td> </tr> <tr> <td style="" id="column1" valign="top"></td> <td style="" id="column2" valign="top"></td> <td style="" id="column3" valign="top"></td> <td style="" id="column4" valign="top" class="style6">First Reading</td> <td style="" id="column5" valign="top" class="style3">Office of the City Clerk</td> <td style="" id="column6" valign="top"></td> <td style="" id="column7" valign="top"></td> <td style="" id="column8" valign="top"></td> </tr> <tr> <td style="" id="column1" valign="top"></td> <td style="" id="column2" valign="top"></td> <td style="" id="column3" valign="top"></td> <td style="" id="column4" valign="top" class="style7"></td> <td style="" id="column5" valign="top" class="style3">Commissioner Michael Gongora</td> <td style="" id="column6" valign="top"></td> <td style="" id="column7" valign="top"></td> <td style="" id="column8" valign="top"></td> </tr> </tbody> <tr> <td style="" id="column1" valign="top"></td> <td style="" id="column2" valign="top"></td> <td style="" id="column3" valign="top"></td> <td style="" id="column4" valign="top"></td> <td style="" id="column5" valign="top"></td> <td style="" id="column6" valign="top"></td> <td style="" id="column7" valign="top"></td> <td style="" id="column8" valign="top"></td> </tr> <tr> <td style="" id="column1" valign="top"></td> <td style="" id="column2" valign="top"></td> <td style="" id="column3" valign="top"></td> <td style="" id="column4" valign="top"></td> <td style="" id="column5" valign="top" colspan="1" class="style8"></td> <td style="" id="column6" valign="top"></td> <td style="" id="column7" valign="top"></td> <td style="" id="column8" valign="top"></td> </tr> <tbody style="page-break-inside: avoid"> <tr> <td style="" id="column1" valign="top"></td> <td style="" id="column2" valign="top" class="style3">R5</td> <td style="" id="column3" valign="top" class="style2">B</td> <td style="" id="column4" valign="top" colspan="2" class="style2"> <a target="_blank" href="CoverSheet.aspx?ItemID=19206&MeetingID=779"> <p>SHORT TERM RENTAL FINE REVISIONS</p> <p>AN ORDINANCE OF THE MAYOR AND CITY COMMISSION OF THE CITY OF MIAMI BEACH, FLORIDA, AMENDING MIAMI BEACH CITY CODE CHAPTER 142, "ZONING DISTRICTS AND REGULATIONS," ARTICLE IV, "SUPPLEMENTARY DISTRICT REGULATIONS," SECTION 142-905, "PERMITTED ACCESSORY USES IN SINGLE-FAMILY DISTRICTS," AT SUBSECTION (b)(5) THEREOF, AND AMENDING SECTION 142-1111, "SHORTTERM RENTAL OF APARTMENT UNITS OR TOWNHOMES," FOR THE LIMITED PURPOSE OF DELETING THE FINE AMOUNTS SPECIFIED THEREIN FOR VIOLATIONS OF THE CITY'S SHORT-TERM RENTAL RESTRICTIONS (INCLUDING CORRESPONDING RESTRICTION ON SPECIAL MASTER'S INABILITY TO WAIVE OR REDUCE SAID FINES), AND SUBSTITUTING THEREFOR THOSE FINE AMOUNTS WITHIN THE STATUTORILY-PRESCRIBED LIMITS SET FORTH IN CHAPTER 162, FLORIDA STATUTES; AND PROVIDING FOR REPEALER, SEVERABILITY, CODIFICATION, AND AN EFFECTIVE DATE. </p> </a> </td> <td style="" id="column6" valign="top"></td> <td style="" id="column7" valign="top"></td> <td style="" id="column8" valign="top"></td> </tr> <tr> <td style="" id="column1" valign="top"></td> <td style="" id="column2" valign="top"></td> <td style="" id="column3" valign="top"></td> <td style="" id="column4" valign="top"></td> <td style="" id="column5" valign="top"></td> <td style="" id="column6" valign="top"></td> <td style="" id="column7" valign="top"></td> <td style="" id="column8" valign="top"></td> </tr> <tr> <td style="" id="column1" valign="top"></td> <td style="" id="column2" valign="top"></td> <td style="" id="column3" valign="top"></td> <td style="" id="column4" valign="top" class="style6">First Reading</td> <td style="" id="column5" valign="top" class="style3">Planning/Office of the City Attorney</td> <td style="" id="column6" valign="top"></td> <td style="" id="column7" valign="top"></td> <td style="" id="column8" valign="top"></td> </tr> <tr> <td style="" id="column1" valign="top"></td> <td style="" id="column2" valign="top"></td> <td style="" id="column3" valign="top"></td> <td style="" id="column4" valign="top" class="style7"></td> <td style="" id="column5" valign="top" class="style3">Mayor Dan Gelber</td> <td style="" id="column6" valign="top"></td> <td style="" id="column7" valign="top"></td> <td style="" id="column8" valign="top"></td> </tr> </tbody> <tr> <td style="" id="column1" valign="top"></td> <td style="" id="column2" valign="top"></td> <td style="" id="column3" valign="top"></td> <td style="" id="column4" valign="top"></td> <td style="" id="column5" valign="top"></td> <td style="" id="column6" valign="top"></td> <td style="" id="column7" valign="top"></td> <td style="" id="column8" valign="top"></td> </tr> <tr> <td style="" id="column1" valign="top"></td> <td style="" id="column2" valign="top"></td> <td style="" id="column3" valign="top"></td> <td style="" id="column4" valign="top"></td> <td style="" id="column5" valign="top" colspan="1" class="style8">Supplemental updated on 9/25/2020 (Memorandum & Ordinance)</td> <td style="" id="column6" valign="top"></td> <td style="" id="column7" valign="top"></td> <td style="" id="column8" valign="top"></td> </tr> </TABLE>
Advertisement
Answer
If I were you I would add few helper methods to avoid similar situation:
<?php foreach($html->find('td#column2.style3') as $e) { // $sponsor3 = $e->parent()->next_sibling()->next_sibling()->next_sibling()->children(4)->plaintext; $parent = getParentSafe($e); $firstSibling = getNextSiblingSafe($parent); $secondSibling = getNextSiblingSafe($firstSibling); $thirdSibling = getNextSiblingSafe($secondSibling); $fourthChild = getChildSafe($thirdSibling, 4); $sponsor3 = is_null($fourthChild) ? "" : $fourthChild->plaintext; echo "Sponsor3 <strong>" . $sponsor3 . "</strong><br>"; } function getParentSafe( $node ) { return is_null($node) ? $node : $node->parent(); } function getNextSiblingSafe( $node ) { return is_null($node) ? $node : $node->next_sibling(); } function getChildSafe( $node, $index ) { if (is_null($node)) { return $node; } $children = $node->children(); return count($children) > $index ? $children[$index] : $node; } ?>
This will make sure php will not crash. That being said, you have a lot clean up to do in your code.