PHP: XML Parsing with simplexml_load_file()

  • PHP’s SimpleXML extension was introduced back in PHP 5.0
  • An increasing number of web services return data in JSON format, but a large number still return XML
  • The code below demonstrates  both reading of : XML Elements and XML Attributes
  • The entire DOM tree is read into memory and returns a SimpleXMLElement PHP object
  • Use this APi with caution for large XML files 

XML data

    <trk>
        <name>Neue Positionsliste 1</name>
        <trkseg>
            <trkpt lat="49.81208" lon="11.353953">
                <ele>379.0</ele>
                <time>2015-12-07T12:47:05.000Z</time>
                <name>Position 1</name>
                <extensions>
                    <nmea:speed>2.45</nmea:speed>
                </extensions>
            </trkpt>
            <trkpt lat="49.812103" lon="11.353962">
                <ele>379.0</ele>
                <time>2015-12-07T12:47:06.000Z</time>
                <name>Position 2</name>
                <extensions>
                    <nmea:speed>2.75</nmea:speed>
                </extensions>
            </trkpt>
      ...

PHP code

 function parseGPX($dirName, $fileName)
  {
  global $gpxArray;
  global $gpxCount;
  
  $gpxArray = simplexml_load_file($dirName.$fileName);
  $gpxCount = count($gpxArray->trk->trkseg->trkpt);
  $i = 0;
  print_r($gpxArray->trk->trkseg->trkpt[0]);
  print_r("First GPX Element:: Lat: ".$gpxArray->trk->trkseg->trkpt[0]["lat"]." - Lon: ".$gpxArray->trk->trkseg->trkpt[0]["lon"]. 
           " - Ele: ".$gpxArray->trk->trkseg->trkpt[0]->ele."\n");
  printf("\n");   
  foreach ($gpxArray->trk->trkseg->trkpt as $gpxElem) 
      {
      $i++;
      if ( $i == 1 || $i == $gpxCount || ( $i % 100) === 0 )
        printf("\n% -4d: Lat: % -10s - Lon:% -10s - Ele: % -6s", $i, $gpxElem["lat"], $gpxElem["lon"], $gpxElem->ele );   
    }    
  printf("\n");   
  print_r("GPX Array Count: ".count($gpxArray->trk->trkseg->trkpt)."\n");
  error_log('gpxCount: '.$gpxCount);
  }

PHP Output

(
    [@attributes] => Array
        (
            [lat] => 49.81208
            [lon] => 11.353953
        )

    [ele] => 379.0
    [time] => 2015-12-07T12:47:05.000Z
    [name] => Position 1
    [extensions] => SimpleXMLElement Object
        (
        )

)
Output:   
First GPX Element:: Lat: 49.81208 - Lon: 11.353953 - Ele: 379.0

1   : Lat: 49.81208   - Lon:11.353953  - Ele: 379.0
100 : Lat: 49.81406   - Lon:11.353427  - Ele: 393.0
200 : Lat: 49.814999  - Lon:11.35364   - Ele: 405.0
300 : Lat: 49.815887  - Lon:11.354074  - Ele: 420.0
400 : Lat: 49.816792  - Lon:11.35475   - Ele: 409.0
500 : Lat: 49.817665  - Lon:11.355126  - Ele: 407.0
600 : Lat: 49.818573  - Lon:11.354907  - Ele: 414.0
700 : Lat: 49.819462  - Lon:11.35405   - Ele: 417.0
800 : Lat: 49.820202  - Lon:11.353247  - Ele: 417.0
900 : Lat: 49.820946  - Lon:11.35268   - Ele: 427.0
1000: Lat: 49.821693  - Lon:11.352285  - Ele: 438.0
1100: Lat: 49.822273  - Lon:11.353273  - Ele: 441.0
1200: Lat: 49.823071  - Lon:11.353742  - Ele: 448.0
1222: Lat: 49.823299  - Lon:11.353806  - Ele: 448.0
GPX Array Count: 1222  

Reference

PHP: Pass an Array to Javascript using AJAX (jquery ) and PHP’s json_encode

PHP Code to build an Array of Arrays

    
    ....
    $container_arr = array();
    $arr = array(
        'src' =>  get_stylesheet_directory().'/images/track1/i3.jpg',
          'log'  => 'Array1:: '.$PHPBufferX,
        'warn'  => $PHPwarnX,
        'error' => $PHPerrorX
          );
  array_push(  $container_arr, (array)$arr );
  
  $arr = array(
        'src' =>  get_stylesheet_directory().'/images/track1/i4.jpg',
          'log'  => 'Array2:: '.$PHPBufferX,
        'warn'  => $PHPwarnX,
        'error' => $PHPerrorX
          ); 
  array_push(  $container_arr,  (array)$arr );
          
  echo json_encode($container_arr);
  error_log('JSON ENCODE ok ...');  
  die();

JavaScript / JQuery Code to read Arrays

jQuery(document).ready(function()
{
var greeting = jQuery("#greeting3").val();
var trackids = jQuery("#trackids").val();
jQuery("#ajax3-button").click(function()
{
console.log('ajax3-button pressed') ;
jQuery.ajax({
type: 'POST',
url :  'http://localhost/wordpress/wp-admin/admin-ajax.php',
data: { action: 'myAjax2', greeting3: greeting, trackids: trackids   },
// dataType: 'html',  /* used for JSON Debugging */
dataType: 'json',
success: function(data, textStatus, XMLHttpRequest)
{
console.log("Returing from AJAX request - Adding greetings to Div:  #divp4 ");

   $.each(data, function(index, obj)
    {
    jQuery("#divp4").append('<p><b>Array Index: '+ (index+1) + '</p>');
    jQuery("#divp4").append('<p><b>Image SRC  : </b>' + obj.src +'</p>');
    jQuery("#divp4").append('<p><b>PHP LOG    : </b>' + obj.log +'</p>');
    jQuery("#divp4").append('<p><b>Warnings   : </b>' + obj.warn +'</p>');
    jQuery("#divp4").append('<p><b>Errors     : </b>' + data.error +'</p>');
    });
   //      jQuery("#divp4").append('<p>'+ data + '</p>');   /* used for JSON Debugging */
},
error: function(XMLHttpRequest, textStatus, errorThrown)
{ alert(errorThrown); }
});
var ih = '<p>AJAX3 button presesed : AJAX request in progress ! - Trackids: ' + trackids +' </p>' ;
document.getElementById("divp3").innerHTML = ih;
console.log('Leaving ajax3-button Ajax action');
});
});

Output:

 
Array Index: 1
Image SRC : D:\xampp\htdocs\wordpress/wp-content/themes/twentyfifteen-child/images/track1/i3.jpg
PHP LOG : Array1:: Greeting from AJAX request 3:: - CWD: : D:\xampp\htdocs\wordpress\wp-admin
Warnings : null
Errors : undefined

Array Index: 2
Image SRC : D:\xampp\htdocs\wordpress/wp-content/themes/twentyfifteen-child/images/track1/i4.jpg
PHP LOG : Array2:: Greeting from AJAX request 3:: - CWD: : D:\xampp\htdocs\wordpress\wp-admin
Warnings : null
Errors : undefined

 PHP Error Log

  • The array output was triggered by a print_r  PHP comand
  • The Output was deleted by running ob_end_clean() before running:  echo json_encode($container_arr);
[04-Dec-2015 16:09:39 UTC] myAjax2()
[04-Dec-2015 16:09:39 UTC] ajaxWrapper():: ob_start with CallBack Function
[04-Dec-2015 16:09:39 UTC] PHP Parse DUMP::
[04-Dec-2015 16:09:39 UTC] JSON ENCODE  ...
[04-Dec-2015 16:09:39 UTC] myObCallback() active ::  Cleaning Current PHP Buffer:: 
Array
(
    [0] => Array
        (
            [src] => D:\xampp\htdocs\wordpress/wp-content/themes/twentyfifteen-child/images/track1/i3.jpg
            [log] => Array1:: Greeting from AJAX request 3::  - CWD: D:\xampp\htdocs\wordpress\wp-admin</
            [warn] =>
            [error] =>
        )
    [1] => Array
        (
            [src] => D:\xampp\htdocs\wordpress/wp-content/themes/twentyfifteen-child/images/track1/i4.jpg
            [log] => Array2:: Greeting from AJAX request 3::  - CWD: : D:\xampp\htdocs\wordpress\wp-admin</
            [warn] =>
            [error] =>
        )

)
[04-Dec-2015 16:09:39 UTC] JSON ENCODE ok - Now Dying ...
[04-Dec-2015 16:09:39 UTC]  -------------- [SHUTDOWNHANDLER]:: Start  -----------------------
[04-Dec-2015 16:09:39 UTC] [logLastError]:: No errors/Warnings found in this PHP Page
[04-Dec-2015 16:09:39 UTC]  -------------- [xx SHUTDOWNHANDLER]:: Leaving:  -----------------------

Reference

 

Handling PHP Parse Errors

Typical PHP Script errors and their default Action

In the following POST we will have a closer look at the following PHP Script Errors 

 Value     Constant     Description
     1     E_ERROR     Fatal run-time errors. Errors that cannot be recovered from. Execution of the script is halted        
     4     E_PARSE     Compile-time parse errors. Parse errors should only be generated by the parser. Script is halted.
     8     E_NOTICE    Run-time notices. The script found something that might be an error, but could also happen when 
                       running a script normaly . Script runs to the END.

Is using set_error_handler() a working solution ?

  • The following error types cannot be handled with a user defined function: E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING,E_COMPILE_ERROR, E_COMPILE_WARNING, and most of E_STRICT raised in the file where set_error_handler() is called.
  • Using set_error_handler is only useful for debugging Warnings [ like uninitialised variables ]
  • If using a user function (error_handler) to handle errors in a script by using set_error_handler() any WARNING  will not get displayed in our register_shutdown_function() at the PHP page end.  This is not expected !
  • As set_error_handler() can’t be used for all errors  we should use register_shutdown_function instead

 

Using register_shutdown_function() to handle PARSE, RUNTIME and WARNINGS

  • Parse Errors can only be handled by using  register_shutdown_function in the top level PHP Page
  • PHP shutdownhandler() uses  error_get_last() to retrieve the latest PHP error/warning
  • NOTE: YOU should disable any error handler ( set by set_error_handler() ) if you want to log even WARNING messages.

PHP Code for our TOP LEVEL Page

 
<?php

include 'phpErrorHandler.php';                   /* defines errorHandler and shutdownHandler function */
// set_error_handler("errorHandler");            /* disable _error_handler when using register_shutdown_function */
                                                 /* If  set_error_handler() is enabled WARNIGNS will be missed in our  registered shutdown function*/
register_shutdown_function("shutdownHandler");
ini_set('display_errors', false);               /* Note PHP errors may break the JSON traffic in our AJAX requests */ 
                                                /* Don't to display any Errors in the Browser Window  */ 
ini_set('error_reporting', E_ALL); 
$handlerType='TOP LEVEL';  
  
echo "<p>____Before Error::</p>";
include 'create_a_php_error.php';                /* The PHP source with an errors */
      /* Note we will never reach this line in case of syntax errors in create_a_php_error.php  */
echo "<p>____After Include:: </p>"; 
runme();                                         /* The function with an error */
echo "<p>____Leaving Page:: </p>";
?>   

PHP Code for our shutdownHandler

 
<?php

function shutdownHandler()   //will be called when php script ends.
{
   global $handlerType;
   logError(" -------------- Inside shutdownHandler: ".$handlerType." -----------------------", "info"); 
   $lasterror = error_get_last();
   if ( $lasterror ===  null )
        logError('[SHUTDOWNHANDLER]:: No errors found in PHP Page',"info");
   else
     {
           // logError('[SHUTDOWNHANDLER]:: Found errors found in PHP Page: - Error Type::  '.$lasterror['type'] ,"info");       
      switch ($lasterror['type'])
       {
            case E_ERROR:
              case E_CORE_ERROR:
              case E_COMPILE_ERROR:
              case E_USER_ERROR:
              case E_RECOVERABLE_ERROR:
              case E_CORE_WARNING:
              case E_COMPILE_WARNING:
              case E_PARSE:    
                {   
                $error = "[SHUTDOWNHANDLER] lvl:" . $lasterror['type'] . " | msg:" . $lasterror['message'] . " | file:" . $lasterror['file'] . " | ln:" . $lasterror['line'];
                      //  echo '<p><b>'.$error.'</b></p>';
                logError($error, "fatal");
                break;
                }
              default:
                {
                $error = "[SHUTDOWNHANDLER: Unknown Type ] LVL:" . $lasterror['type'] . " | msg:" . $lasterror['message'] . " | file:" . $lasterror['file'] . " | ln:" . $lasterror['line'];
                  logError($error, "fatal"); 
                  }
          }
    }
}

function logError($error, $errlvl)
{
  error_log($error);                /* Write to PHP error log */ 
  echo '<p><b>'.$error.'<b></p>';   /* Display the error in our PHP page */
}

?>

PHP Code to be tested –  Runtime Warningthrows E_NOTICE error

 
<?php 
  function runme()
      {
      global $handlerType;
      $handlerType ='2nd LEVEL';     
      echo "<p><b>function runme():: This function creates a PHP Warning , PHP Runtime Error or PHP Syntax Error ! </b></p>";
    
    /* Error1 : Runtime Warning - throws E_NOTICE error */ 
    echo $test;
      
      echo "<p>Leaving function runme - Now dying !</p>";
      die();
    }
?>

HTML Output:     
____Before Error::
____After Include::
function runme():: This function creates a PHP Warning , PHP Runtime Error or PHP Syntax Error !
Leaving function runme - Now dying !
-------------- Inside shutdownHandler: 2nd LEVEL -----------------------
[SHUTDOWNHANDLER: Unknown Type ] LVL:8 | msg:Undefined variable: test | file:D:\xampp\htdocs\create_a_php_error.php | ln:23

PHP Log :
[29-Nov-2015 18:16:31 Europe/Berlin] PHP Notice:  Undefined variable: test in D:\xampp\htdocs\create_a_php_error.php on line 23
[29-Nov-2015 18:16:31 Europe/Berlin]  -------------- Inside shutdownHandler: 2nd LEVEL -----------------------
[29-Nov-2015 18:16:31 Europe/Berlin] [SHUTDOWNHANDLER: Unknown Type ] LVL:8 | msg:Undefined variable: test | 
                                     file:D:\xampp\htdocs\create_a_php_error.php | ln:23
  • As we get only  E_NOTICE Warning  the script runs to the end
  • Our PAGE SHUTDOWNHANDLER is able to retrieve  this WARNING

PHP Code to be tested –  Fatal Runtime error :  E_ERROR

 
<?php  
  function runme()
      {
      global $handlerType;
      $handlerType ='2nd LEVEL';     
      echo "<p><b>function runme():: This function creates a PHP Warning , PHP Runtime Error or PHP Syntax Error ! </b></p>";
    
    /* Error2 : Runtime Error - throws E_ERROR */
     echo "<p>Curent Working directory: ".getcd() . "</p>";   
  
      echo "<p>Leaving function runme - Now dying !</p>";
      die();
    }
?>

HTML Output:
____Before Error::
____After Include::
function runme():: This function creates a PHP Warning , PHP Runtime Error or PHP Syntax Error !
-------------- Inside shutdownHandler: 2nd LEVEL -----------------------
[SHUTDOWNHANDLER] lvl:1 | msg:Call to undefined function getcd() | file:D:\xampp\htdocs\create_a_php_error.php | ln:26   

PHP Error LOG:
[29-Nov-2015 18:24:09 Europe/Berlin] PHP Fatal error:  Call to undefined function getcd() in 
                                      D:\xampp\htdocs\create_a_php_error.php on line 26
[29-Nov-2015 18:24:09 Europe/Berlin]  -------------- Inside shutdownHandler: 2nd LEVEL -----------------------
[29-Nov-2015 18:24:09 Europe/Berlin] [SHUTDOWNHANDLER] lvl:1 | msg:Call to undefined function getcd() | 
                                     file:D:\xampp\htdocs\create_a_php_error.php | ln:26
  • Note this script was aborted due to fatal E_ERROR error

PHP Code to be tested –  Fatal PARSE error :  E_PARSE

 
<?php  
  function runme()
      {
      global $handlerType;
      $handlerType ='2nd LEVEL';     
      echo "<p><b>function runme():: This function creates a PHP Warning , PHP Runtime Error or PHP Syntax Error ! </b></p>";
    
      /* Error 3: Syntax error -  throws E_PARSE : this is a fatal error an can only handled in the TOP level PHP page  */
      logS(    
      
      echo "<p>Leaving function runme - Now dying !</p>";
      die();
    }
?>

HTML Output:
____Before Error::
-------------- Inside shutdownHandler: TOP LEVEL -----------------------
[SHUTDOWNHANDLER] lvl:4 | msg:syntax error, unexpected 'echo' (T_ECHO) | file:D:\xampp\htdocs\create_a_php_error.php | ln:31

PHP Error LOG:
[29-Nov-2015 18:31:07 Europe/Berlin] PHP Parse error:  syntax error, unexpected 'echo' (T_ECHO) in 
                                     D:\xampp\htdocs\create_a_php_error.php on line 31
[29-Nov-2015 18:31:07 Europe/Berlin]  -------------- Inside shutdownHandler: TOP LEVEL -----------------------
[29-Nov-2015 18:31:07 Europe/Berlin] [SHUTDOWNHANDLER] lvl:4 | msg:syntax error, unexpected 'echo' (T_ECHO) | 
                                     file:D:\xampp\htdocs\create_a_php_error.php | ln:31
  • Note this script was aborted due to fatal E_PARSE error
  • Only if we have registered a SHUTDOWNHANDLER in our top level page we can catch this type of PARSE errors

Reference