← Back to PHP Course | Chapter 15: Web Development | Lesson 11 of 12

PHP AJAX XML

While JSON dominates modern AJAX, some systems -- especially older APIs or ones integrating with legacy XML-based services -- still expect AJAX responses in XML format. PHP can build and return XML from an AJAX endpoint using the same SimpleXML and DOM tools covered earlier, just with an XML-appropriate content type.

Returning XML from a PHP Endpoint

An AJAX endpoint can build and return an XML document instead of JSON, using DOMDocument (covered in the DOM Parser topic) to construct it safely, then outputting it with the appropriate text/xml content type header.

Note: Use DOMDocument to build XML programmatically rather than manually concatenating tag strings, which avoids malformed output from un-escaped special characters.

Warning: A raw string like "<name>" typed directly by a user, if concatenated unescaped into a manually built XML string, breaks the document's structure -- DOM handles this escaping automatically.

Example: Returning XML from a PHP Endpoint

php
<?php
header("Content-Type: text/xml");
$dom = new DOMDocument();
$root = $dom->createElement("response", "success");
$dom->appendChild($root);
echo $dom->saveXML();
?>

Parsing an XML AJAX Response in JavaScript

The browser's built-in DOMParser can parse a raw XML response string into a navigable document, similar to how PHP's own DOM extension works -- response.text() retrieves the raw XML text, and new DOMParser().parseFromString() converts it into a queryable document.

Note: Use querySelector() or getElementsByTagName() on the parsed XML document, exactly like you would on an HTML document's DOM.

Warning: fetch()'s response.xml() method does not exist -- XML responses must be retrieved as text with response.text() and then parsed manually with DOMParser.

Example: Parsing an XML AJAX Response in JavaScript

php
<?php
// JS: new DOMParser().parseFromString(await response.text(), "text/xml")
header("Content-Type: text/xml");
echo "<response>ok</response>";
?>

Building an XML Response from Database Data

Combining a database query with XML output follows the same pattern as the JSON case -- fetch rows, then build an XML element for each one using DOMDocument, appending each row as a child element of the response document.

Note: Build one XML element per database row inside a loop, appending each to the same parent element, mirroring how you would build a JSON array from the same data.

Warning: Building XML from many rows in a tight loop with DOMDocument is more verbose than the equivalent JSON approach, since each element and its children must be explicitly created and appended.

Example: Building an XML Response from Database Data

php
<?php
$db = new SQLite3(':memory:');
$db->exec("CREATE TABLE products (name TEXT)");
$db->exec("INSERT INTO products VALUES ('Book')");
$dom = new DOMDocument();
$root = $dom->createElement("products");
$result = $db->query("SELECT * FROM products");
while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
    $item = $dom->createElement("product", $row['name']);
    $root->appendChild($item);
}
$dom->appendChild($root);
echo $dom->saveXML();
?>

Choosing Between XML and JSON for a New Endpoint

For a brand-new AJAX endpoint with no existing constraint, JSON is almost always the simpler, more efficient choice -- reach for XML specifically when integrating with a system that already expects or produces XML, not as a default starting point.

Note: Default new AJAX endpoints to JSON unless there is a specific, existing reason (like a legacy API contract) requiring XML instead.

Warning: Mixing XML and JSON endpoints inconsistently across the same project, without a clear reason for the split, makes the codebase harder to maintain and the client-side code more complicated.

Example: Choosing Between XML and JSON for a New Endpoint

php
<?php
echo "Use JSON by default; XML only when integrating with a system that already expects it";
?>

Validating an XML Response Structure

Before an AJAX endpoint's XML response is considered reliable, it is worth confirming the DOMDocument actually produces valid, well-formed XML -- calling loadXML() on the saveXML() output as a sanity check, or testing directly against the endpoint's URL and inspecting the raw response.

Note: Test a new XML-returning endpoint by fetching it directly (curl or a browser) and confirming the raw output is valid XML before wiring up any JavaScript to consume it.

Warning: A PHP error or warning accidentally output before the XML content (like a stray notice) breaks the response's XML validity, causing DOMParser to report a parse error on the client side.

Example: Validating an XML Response Structure

php
<?php
$dom = new DOMDocument();
$root = $dom->createElement("response", "ok");
$dom->appendChild($root);
$xmlString = $dom->saveXML();
$check = new DOMDocument();
$isValid = $check->loadXML($xmlString);
echo $isValid ? "Well-formed XML" : "Invalid XML";
?>
Common Mistakes
  1. Forgetting to set the Content-Type: text/xml (or application/xml) response header, which can cause the browser or JavaScript XML parser to misinterpret the response.
  2. Manually concatenating XML tags around variable values as strings, risking malformed XML if a value happens to contain a character like < or & that needs escaping.
  3. Mixing XML and JSON response formats inconsistently across different endpoints in the same project, forcing the JavaScript to handle each one differently.
Chapter Summary
  • An AJAX endpoint returning XML should set the Content-Type: text/xml header so the client correctly interprets the response.
  • DOMDocument or SimpleXML should be used to build the XML response programmatically, rather than manually concatenating tag strings.
  • JavaScript's fetch API can retrieve and parse an XML response with response.text() followed by the DOMParser API.
Browser Support

XML AJAX responses work in every modern browser via fetch() and the built-in DOMParser API; PHP's DOM and SimpleXML extensions produce standard, compliant XML.

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.