PHP XML DOM
PHP XML DOM Parser
Section titled “PHP XML DOM Parser”PHP provides built-in extensions for parsing and manipulating XML documents. The DOM (Document Object Model) extension is one powerful option that treats an XML document as a tree structure in memory.
The XML DOM Parser
Section titled “The XML DOM Parser”The DOM parser loads the entire XML document into memory and represents it as a tree of objects (nodes). This allows for complex navigation, modification, and querying of the XML structure.
Consider this simple XML fragment:
<?xml version="1.0" encoding="UTF-8"?><message> <from>Jani</from></message>The DOM parser views this as a hierarchy:
- Document Node
- Element Node:
<message> -
Text Node: (Whitespace between `<message>` and `<from>`)
-
Element Node: `<from>`
-
Text Node: "Jani"
-
Text Node: (Whitespace after `</from>`)
Understanding this tree structure is key to using the DOM API effectively.
Alternative: For simpler XML reading tasks, especially with large files where memory is a concern, the SimpleXML extension often provides an easier-to-use interface. For stream-based processing of very large files, the XMLReader and XMLWriter extensions are more suitable.
Installation
Section titled “Installation”The DOM extension (ext-dom) is typically compiled and enabled by default in most PHP installations. No separate installation is usually required.
Example XML File (note.xml)
Section titled “Example XML File (note.xml)”We’ll use the following note.xml file for the examples:
<?xml version="1.0" encoding="UTF-8"?><note importance="high"> <to>Tove</to> <from>Jani</from> <heading>Reminder</heading> <body>Don't forget me this weekend!</body></note>Loading and Saving XML with DOM
Section titled “Loading and Saving XML with DOM”The core class is DOMDocument. We can load an XML file or string into it and save it back out.
Example: Load and Print
Section titled “Example: Load and Print”<?php// Create a new DOMDocument object$xmlDoc = new DOMDocument();
// Load the XML file (error suppression '@' can be used, but checking return value is better)// For better formatting and whitespace handling:$xmlDoc->preserveWhiteSpace = false;$xmlDoc->formatOutput = true;
if ($xmlDoc->load('note.xml')) { // Save the loaded XML back to a string $xmlString = $xmlDoc->saveXML();
// Output the XML (ensure proper content type if serving via web) // header('Content-Type: application/xml; charset=utf-8'); echo htmlspecialchars($xmlString, ENT_QUOTES, 'UTF-8');} else { echo "Failed to load note.xml"; // Add proper error handling, e.g., using libxml_get_errors()}?>This code creates a DOMDocument object, loads note.xml into it (disabling whitespace preservation and enabling output formatting for readability), and then uses saveXML() to output the document’s content as a string.
Navigating and Extracting Data
Section titled “Navigating and Extracting Data”Once loaded, you can navigate the DOM tree to extract specific data.
Example: Loop through child elements
Section titled “Example: Loop through child elements”<?php$xmlDoc = new DOMDocument();$xmlDoc->preserveWhiteSpace = false; // Ignore whitespace text nodes$xmlDoc->load('note.xml');
// Get the root element (<note>)$rootElement = $xmlDoc->documentElement;
echo "Reading elements directly under <note>:\n";
// Iterate through child nodes of the root elementforeach ($rootElement->childNodes as $item) { // Check if it's an element node (type 1) to avoid text nodes etc. if ($item->nodeType === XML_ELEMENT_NODE) { // nodeName gives the tag name (e.g., 'to') // nodeValue of an element itself is often null/empty, // text content is in its child text node. // textContent gets the combined text content of the node and its descendants. echo $item->nodeName . " = " . $item->textContent . "\n"; }}
// Accessing attributes (e.g., the 'importance' attribute of <note>)if ($rootElement->hasAttribute('importance')) { $importance = $rootElement->getAttribute('importance'); echo "\nImportance attribute: " . htmlspecialchars($importance, ENT_QUOTES, 'UTF-8') . "\n";}
// Using getElementsByTagName to find specific elementsecho "\nFinding all <body> elements:\n";$bodyElements = $xmlDoc->getElementsByTagName('body');foreach ($bodyElements as $body) { echo "Body content: " . $body->textContent . "\n";}?>Expected Output:
Reading elements directly under <note>:to = Tovefrom = Janiheading = Reminderbody = Don't forget me this weekend!
Importance attribute: high
Finding all <body> elements:Body content: Don't forget me this weekend!Explanation:
documentElement: Accesses the root element of the XML document.childNodes: ADOMNodeListcontaining all direct children (including text nodes, comment nodes, etc.).nodeType === XML_ELEMENT_NODE: Checks if a node is an actual element (like<to>,<from>) rather than whitespace or a comment.nodeName: Returns the tag name of the element.textContent: Returns the textual content of the node and all its descendants.getAttribute()/hasAttribute(): Used to access element attributes.getElementsByTagName(): Finds all elements with a specific tag name anywhere within the context node (or the whole document).
Common Pitfall: Be mindful of whitespace nodes between elements if preserveWhiteSpace is not set to false. They will appear in childNodes and might require explicit checks (nodeType !== XML_TEXT_NODE or checking if trim($node->nodeValue) is empty).
Tip: For more complex queries, especially on large documents, consider using DOMXPath which allows you to use XPath expressions to select nodes.
Further Learning
Section titled “Further Learning”The DOM extension provides many more capabilities, including creating new nodes, modifying existing ones, deleting nodes, and working with namespaces. Consult the official PHP documentation for DOMDocument, DOMElement, DOMNode, DOMXPath, and related classes for comprehensive details.