Whether you’re looking to use plaintext, JSON, or XML in your Ajax calls, WordPress (WP) has you covered. With regards to the latter, the WP_Ajax_Response class is your best bet for easy Ajax coding. It takes an Array object and converts it into XML-formatted text, ready to be parsed back on the client-side. As we’ll see here today, even that part is partially taken care of by WP for you.
Comparing JSON to XML Output
In the Binding PHP Functions to WordPress’s Ajax Handler article, we saw an example of WP code that generates a JSON-formatted string to send back to the browser. Converting our $new_menus Array into JSON-formatted string was only a matter of running through the PHP json_encode() function and setting the response header content-type to “application/json”. On the browser side, the data was received as a JavaScript Object, ready to be read and manipulated:
function myajax_update_cached_menus() { $restaurantData = $_POST['data']; $new_menus = array(); foreach ($restaurantData as $id => $value) { $menu = array( "metaData" => new restaurant_data( $id ), "menus" => restaurant_data::get_menu_download_data_parent( $id ) ); $new_menus[$id] = $menu; } // response output header( "Content-Type: application/json" ); echo json_encode($new_menus); // IMPORTANT: don't forget to "exit" exit; } // if both logged in and not logged in users can send this Ajax request, // add both of these actions, otherwise add only the appropriate one add_action( 'wp_ajax_nopriv_myajax-update-cached-menus', 'myajax_update_cached_menus' ); add_action( 'wp_ajax_myajax-update-cached-menus', 'myajax_update_cached_menus' );
Using the WP_Ajax_Response() object, the same function can be designed to return XML-formatted data:
function myajax_update_cached_menus() { $restaurantData = $_POST['data']; $new_menus = array(); foreach ($restaurantData as $id => $value) { $menu = array( "metaData" => new restaurant_data( $id ), "menus" => restaurant_data::get_menu_download_data_parent( $id ) ); $new_menus[$id] = $menu; } $response = array( 'what'=>'menusXML', 'action'=>'show_menu', 'id'=>'1', // 'data'=>'', 'supplemental'=>$new_menus ); $xmlResponse = new WP_Ajax_Response($response); $xmlResponse->send(); }
Instantiating the WP_Ajax_Response() Object
The WP_Ajax_Response is an Object and not a function, so we need to instantiate it using the new keyword. Its constructor accepts only one argument, but it’s a big one: an array of options with a number of key=>value pairs, as follows:
- ‘what’: A string that will be used as the name of the root XML element.
- ‘action’: A boolean or string that will be added to the response element’s action attribute.
- ‘id’ This is either an integer (usually 1) or a WP_Error object, should you need to return an error. Most commonly, the id value used is a boolean, whereby 1 signifies success and 0 a failure condition.
- ‘old_id’: This is false by default, but you can provide an integer for the previous id, if needed.
- ‘position’: This is an integer or a string where -1 = top, 1 = bottom, ‘html ID’ = after, and ‘-html ID’ = before. Unfortunately, the docs don’t explain what the parameter actually does!
- ‘data’: A string containing HTML output content or a message. This value is ignored if you pass a WP_Error object as the id.
- ‘supplemental’: This can an associative array of strings, which will be inserted as children of the <supplemental> element. Keys become element names, and values are embedded in CDATA within those elements. This parameter is useful for passing additional information to the browser (such as arrays of menus).
Here is the XML code produced by the above function. Note the inclusion of the ‘menusXML’ ‘what’, ‘show_menu’ ‘action’, and ‘1’ ‘id’ key values in the XML:
<?xml version='1.0' standalone='yes'?> <wp_ajax> <response action='show_menu_1'> <menusXML id='1' position='1'> <response_data><![CDATA[]]></response_data> <supplemental> <metaData> <post_title>Rob's Bistro</post_title> <address> 22 Acacia Avenue, London, WC2E 9BH</address> <phone>020 5555 5555</phone> <cuisines>italian </cuisines> <url>www.robgravelle.com</url> </metaData> <menus> <sectiondescription> <breakfast></breakfast> <small Italian plates></small Italian plates> <soups></soups> <antipasti></antipasti> <salads></salads> <pasta></pasta> <fish></fish> <meat></meat> <side dishes></side dishes> <desserts></desserts> <fixed price menu>> <menu for children></menu for children> </sectiondescription> <breakfast>Breakfast bread tin. Vegetarian.</breakfast> <breakfast>3.95</breakfast> <breakfast>Croissant and pastries. Vegetarian.</breakfast> //... </menus> </menusXML> </response> </wp_ajax>
Parsing the Response
All that’s left to do now is parse the XML response on the client-side so that we can use it as an object, much like we did with our JSON response. This is accomplished using the wpAjax JavaScript object. It’s part of the wp-ajax-response.js script, so we need to include it as a dependency for our own scripts. It’s built on jQuery so that also needs to be referenced:
wp_enqueue_script( 'admin_url', get_template_directory_uri() . '/js/myajax.js', array( 'jquery', 'wp-ajax-response' ) );
For those of you who are highly inquisitive, here is the source code for the wp-ajax-response.js script.
The wpAjax object has a method called parseAjaxResponse(). It accepts two arguments: the response data and the ID of a field in which to display messages. The returned value is an Array of response objects. Therefore the standard is to iterate over the returned object’s responses property using jQuery each(). Inside the passed function, we can access the response’s attributes (as described above). In the Ajax success function below, a switch statement determines that the what attribute is our “menusXML”. The data is then retrieved via the response’s supplemental property:
function(data,code,xhr) { var restaurantInfo, res = wpAjax.parseAjaxResponse(data, 'result'); $.each( res.responses, function() { switch(this.what) { case "menusXML": restaurantInfo = this.supplemental; //display the menus… break; } } }
Conclusion
There is one part of working with XML data that we didn’t explore here today, and that is error handling. I’m saving that for an up-coming article on Nonces. You may not have heard of them before, but if you’ve ever gone to a doctor’s office, government service center, or butcher shop, you’re probably already intimately familiar with the concept.