Schaake.nu

PHP DOM

Gepost in /PHP ontwikkeling/Software op 01 Juli 2012
Deze blog is geschreven door Christiaan Schaake

PHP DOM Extentie

Het Document Object Model (DOM) is een standaard om XML documenten als objecten te benaderen. Voor Pluto, mijn eigen content management system en de software waar deze website op draaid is gebaseerd op XML. Alle pagina's zijn als XML opgeslagen, maar ook de structuur van de site en alle parameter files zijn als XML opgeslagen. Deze blog behandeld een aantal basis handelingen in PHP DOM.

DOM document lezen en schrijven

De basis voor een XML in DOM is de class DOMDocument. Een object van deze classe bevat de gehele XML. Een document kan op 2 manieren gemaakt worden. Inlezen vanuit b.v. een string of bestand. Of beginnen met een lege DOMDocument en deze opbouwen met methodes.

De meeste simpele en leesbare vorm is vanuit een string welke een XML bevat een DOMDocument object creeëren.

$xml = '<?xml version="1.0" encoding="UTF-8"?>';
$xml .= '<books>';
$xml .= ' <book>';
$xml .= ' <title>101 sprookjes</title>';
$xml .= ' <price currency="EUR">12.10</price>';
$xml .= ' </book>';
$xml .= ' <book>';
$xml .= ' <title>101 sprookjes</title>';
$xml .= ' <price currency="EUR">12.10</price>';
$xml .= ' </book>';
$xml .= '</books>';

$DOM = new DOMDocument();
$DOM->preserveWhiteSpace = FALSE;
$DOM->formatOutput = TRUE;

$DOM->loadXML($xml);

echo $DOM->saveXML();

Met het commando 'new DOMDocument()' wordt een nieuw object van het type DOMDocument gemaakt. Dit object is nog leeg. De parameter formatOutput geeft straks een mooie geformateerde output, de preserveWhiteSpace is nodig om eerst de opmaak te verwijderen. Standaard worden alle XML element namelijk achter elkaar weergegeven. Middels de methode 'LoadXML' wordt de XML ingeladen vanuit een string. Indien de string een foute XML bevat wordt een foutmelding weergegeven. Deze foutmelding bevat meestal exact wat er niet goed is.

Met de methode 'saveXML' kan het DOM object weer vertaald worden naar een string. Dit is de eenvoudigste methode om te debuggen hoe de DOM er op een bepaald moment uit ziet.

DOM uitlezen

Naast de in het voorgaande hoofdstuk beschreven methode 'saveXML' kan een DOM ook per element of attribute uitgelezen worden. Hieronder volgen een aantal basis methoden om gegevens uit een DOM te lezen. De voorbeelden gaan er van uit dat de in het voorgaande hoofdstuk beschreven DOMDocument is aangemaakt en ingelezen.

Elementen uitlezen

Stel we willen de waarden weten van de title elementen. We kunnen dan gebruik maken van de methode 'getElementsByTagName'. Deze methode geeft een nodelist object terug. Met dit nodelist object kunnen we de losse nodes uitlezen waarna de element naam en waarde uitgelezen kunnen worden.

foreach($DOM->getElementsByTagName('title') as $element) {
echo $element->nodeName . ' = ' . $element->nodeValue . "\n";
}

We hoeven niet het gehele pad op te geven naar het te zoeken element, maar kunnen meteen het juiste element opgeven. Het string '$element' bevat een node object. Dit object kent oa. de parameters 'nodeName' en 'nodeValue'.

Indien alleen het eerste element 'title' uitgelezen moet worden kan dit ook direct. Het object 'nodelist' kent ook de methode 'item' waarmee direct het juiste node object geselecteerd worden.

echo $DOM->getElementsByTagName('title')->item(0)->nodeName
. ' = ' . $DOM->getElementsByTagName('title')->item(0)->nodeValue;

Deze methode is met name handig wanneer maar één element verwacht wordt, b.v. bij uitlezen van configuratie XML's.

Attributen uitlezen

Stel we willen de prijs en de currency van de boeken weten. De currency is een attribute van het element prijs.

foreach($DOM->getElementsByTagName('price') as $element) {
echo $element->nodeValue . ' ' . $element->getAttribute('currency');
}

De variabele $element is een 'node' object. Dit object kent de methode 'getAttribute' waarmee direct de waarde van een attribute uitgelezen kan worden.

XPath expressie

Bij de voorgaande methode kan een bepaald element worden geselecteerd. Echter kan een XML ook op een meer geavanceerde methode worden geraadpleegd. Dit kan met behulp van XPath expressies. PHP DOM heeft hiervoor een eigen classe genaamd DOMXPath. Voordat de XPath expressie gebruikt kan worden moet er een XPath object worden aangemaakt. Hierna kan met behulp van een XPath expressie gegevens worden uitgelezen uit de DOM.

$XPath = new DOMXPath($DOM);

$entries = $XPath->query('/books/book[price < 10]/title');
echo 'Book < 10 euro : ' . $entries->item(0)->nodeValue;

Eerst maken we een XPath object van het DOM object. Daarna voeren we een query uit om alle boeken te selecteren waarbij het price element minder dan 10 bevat. De variable $entries bevat een DOMNodeList object waarvan we als voorbeeld de waarde van het eerste element uitlezen.

Zolang de DOM niet wijzigd kan het XPath object hergebruikt worden. Indien de DOM wordt aangepast moet het XPath object opnieuw gecreeërd worden.

Creeëren van een DOM

Naast het importeren van een string welke een valide XML bevat kan een DOM ook vanaf niets worden opgebouwd. Dezelfde functionaliteit kan ook gebruikt worden om een DOM uit te bereiden. Als voorbeeld wordt de eerdere XML nagebouwd met DOM functies.

Element aanmaken

We maken eerst het root element 'books' aan. Hiervoor moeten we een nieuwe DOM creeëren. Binnen de DOM maken we een nieuw element 'books'. Dit element 'zweeft' nu binnen de DOM. Via de methode 'appendChild' wordt het nieuwe element gekoppeld aan de root van de DOM.

$DOM = new DOMDocument('1.0','UTF-8');
$DOM->formatOutput = TRUE;

$books = $DOM->createElement('books');
$DOM->appendChild($books);

echo $DOM->saveXML();

We gebruiken de methode 'saveXML' om het resultaat te tonen. De parameter 'formatOutput' zorgt voor een mooie layout t.b.v. de leesbaarheid. De volgende stap is het toevoegen van het eerste book element.

$book = $DOM->createElement('book');
$books->appendChild($book);

$book2 = $DOM->createElement('book');
$books->appendChild($book2);

Het nieuwe element 'book' wordt gemaakt door de methode van DOM. Echter het element moet toegevoegd worden als child element van books. Hierdoor wordt de methode 'appendChild' aangeroepen in $books.

<?xml version="1.0" encoding="UTF-8"?>
<books>
<book/>
<book/>
</books>

Indien het element books nogmaals toegevoegd moet worden is het niet mogelijk om het Element in $book opnieuw als child toe te voegen, immers het Element is reeds gekoppeld. Er moet dus eerste een nieuw element worden gemaakt met de methode 'createElement' voor deze kan worden toegevoegd.

Element met waarde aanmaken

Met de methode 'createElement' kan ook rechtstreeks een waarde worden meegegeven aan een element. De onderstaande code maakt in één regel een nieuw element met text waarde aan.

$book->appendChild($DOM->createElement('title', '101 sprookjes'));

Een element met waarde kan geen childs bevatten. Wel kunnen er attributen worden gekoppeld.

Attribute toevoegen

Aan een element kan een attribute gekoppeld worden. Een attribute kan rechtstreeks aangemaakt worden aan het element. Hiervoor hoeft niet eerste een 'zwevend' attribute gecreeërd te worden binnen de DOM.

$price = $DOM->createElement('price', '12.10'); $price->setAttribute('currency', 'EUR');
$book->appendChild($price);

Met de functie 'setAttribute' wordt rechtstreeks een attribute met waarde gekoppeld. Hiervoor hoeft het element nog niet gekoppeld te zijn aan de DOM. De regel met 'appendChild' mag dus voor of na de regel met setAttribute komen.

Volledig voorbeeld

De volledige code om de voorbeeld XML te construëren is als volgt:

// Maak een lege DOM $DOM = new DOMDocument('1.0','UTF-8');
$DOM->formatOutput = TRUE;

// Maak het root element books
$books = $DOM->createElement('books');
$DOM->appendChild($books);

// Maak het child element book
$book = $DOM->createElement('book');
$books->appendChild($book);

// Het child element title met text direct gekoppeld
$book->appendChild($DOM->createElement('title', '101 sprookjes'));

// Het child element price met text
$price = $DOM->createElement('price', '12.10');

// Het element price krijg zijn attribute
$price->setAttribute('currency', 'EUR');

// Voeg het element child to aan book
$book->appendChild($price);

// Maak het 2e book element
$book2 = $DOM->createElement('book');
$books->appendChild($book2);

// Maak de elementen title en price met hun text waarden
$book2->appendChild($DOM->createElement('title', 'Roodkapje'));
$price = $DOM->createElement('price', '9.45');
$book2->appendChild($price);

// Voeg de attribute toe aan de price
$price->setAttribute('currency', 'EUR');

echo $DOM->saveXML();

De voorbeeld code produceerd de zelfde XML als boven in dit artikel.

<?xml version="1.0" encoding="UTF-8"?>
<books>
<book>
<title>101 sprookjes</title>
<price currency="EUR">12.10</price>
</book>
<book>
<title>Roodkapje</title>
<price currency="EUR">9.45</price>
</book>
</books>

Met deze korte beschrijving is het mogelijk om alle basis handelingen met DOM uit te voeren.

Deze blog is getagd als DOM PHP Programmeren XML

Google
facebook