Hur du skapar en XML-feed i PHP och MySQL

I denna artikel går jag igenom hur du skapar ett xml-dokument med hjälp av PHP's inbyggda XML-funktion: DOM.

Introduktion

PHP har en inbyggd samling av funktioner som kallas DOM. Med dessa funktioner kan du enkelt skapa egna så kallade XML-feeds som är användbart vid flera olika tillfällen.

Det mest förekommande användningsområdet för XML är då du har information lagrad i t.ex en MySQL-databas och vill erbjuda andra webbplatser eller dylikt att läsa in denna information utan att lämna ut inloggningsuppgifterna till din databas.

Förusättningar

För att du skall kunna nyttja de funktioner som jag beskriver nedanför så krävs det att tidigare nämnda DOM-funktioner är aktiverade på det webbhotell du använder. Mer information om hur du tar reda på detta hittar du på PHP's egna hemsida: http://se2.php.net/manual/sv/ref.dom.php

Hur du skapar själva XML-dokumentet

Börja med att skapa ett tomt dokument som du döper till t.ex "xmlfeed.php".

Först av allt lägger vi in koden för att ansluta till vår databas. I detta exempel utgår jag från att vi använder MySQL: 

if(!$dbconnect = mysql_connect('localhost', 'user', 'pass')) {
   echo "Connection failed to the host 'localhost'.";
   exit;
}
if(!mysql_select_db('test')) {
   echo "Cannot connect to database 'test'";
   exit;
} 

Nu är du ansluten till databasen. Vi fortsätter med att göra en databasförfrågan.

$databas = 'mintabell';
$query = "SELECT * FROM $databas";
$dbresult = mysql_query($query, $dbconnect);

Nu har vi gjort en databasförfrågan och resultaten ligger i variablen $dbresult
Nu är det dags att börja skapa vårat XML-dokument.

För att skapa ett nytt XML-dokument anropar vi den inbyggda php-funktionen "DomDocument": 

$xml = new DomDocument('1.0'); 

Nu har vi skapat variabeln $xml som innehåller ett nytt tomt XML-dokument i xml-versionen "1.0".
Det är nu dags att börja lägga in vår data i dokumentet.

Varje XML-dokument måste ha ett baselement

I varje XML-dokument måste det finnas ett baselement, ett så kallat "root"-element.

All data som skall läsas in skall placeras i detta baselement.

Vad du döper baselementet har ingen betydelse.
Koden för att skapa ett baselement ser ut så här:

$baselement = $xml->createElement('baselement');
$baselement = $xml->appendChild($baselement);

För er som har jobbat med javascript så känns dessa kommandon rätt bekant.

Med hälp av funktionen "createElement" skapar vi själva elementet.
Funktionen "appendChild" ansluter vårt baselement till vårt XML-dokument.

Lägga in resterande data till vårt XML-dokument

Nu när vi har skapat ett baselement kan vi börja fylla XML-dokumentet med den information vi hämtade från databasen.

Jag använder en "while"-loop för att läsa in alla rader som lästes in i vår databasförfrågan:

while($row = mysql_fetch_assoc($dbresult)) {

För varje rad i databasen kan vi nu lägga till nya element till vårt XML-dokument. 

Syntaxen för att göra det är likadan som då vi skapade vårat baselement. Kom bara ihåg att döpa det nya element till något annat än vad du döpte baselementet till (i detta fall döper vi det till "element"):

$element = $xml->createElement('element');
$element = $baselement->appendChild($element);

Lägg märke till att det är vårat XML-dokument ($xml) som skapar det nya elementet, men det är vårat baselement som ansluter vårat nya element till XML-trädet.

Nu har du skapat ett nytt element som placerats i vårat baselement. Det nya elementet har fått namnet "element" och är helt tom på data. Om du skulle köra denna kod nu (*) så skulle det se ut ungefär så här om vår datasförfrågan innehöll tre träffar:

<?xml version="1.0"?>
<baselement>
<element></element>
<element></element>
<element></element>
</baselement>

* För att kunna se något resultat i din webbläsare så måste du använda kommandot "saveXML" som jag återkommer till lite senare. Om du vill testa dig fram redan nu med att se hur resultatet blir kan du göra det genom att lägga in följande kod längst ner i dokumentet:

$xmlstrang = $xml->saveXML();
print $xmlstrang;

För att vi nu skall kunna fylla våra "<element></element>" med informationen som vi läst in från databasen upprepar du samma process som du gjorde tidigare.

Säg att vi vill läsa in varje tabellfält ur databasraden till våra "element"-taggar:
Vi börjar med att skapa en "foreach"-loop som går igenom varje tabellfält i vår databasrad "$row".

foreach($row as $namn => $varde){

För varje värde som raden innehåller skapar vi nu ett nytt element som vi sedan ansluter till vårat tidigare skapade "$element"-element.

$faltnamn = $xml->createElement($namn);
$faltnamn = $element->appendChild($faltnamn);

Fortfarande så skapar vi ett nytt element med hjälp av vårat XML-dokument ($xml).
Den här gången är det dock vår "$element" som ansluter vårat fältvärde till XML-dokumentet och inte baselementet.
Detta på grund av att det är vår "<element>"-tagg som skall innehålla det nya elementet, och inte baselementet.

Vi antar nu att vår databastabell innehöll våran hemsidas nyheter och hade tre tabellfält: id, rubrik och beskrivning.

Vårat XML-dokument kommer då att se ut ungefär så här just nu:

<?xml version="1.0"?>
<baselement>
<element>
   <id></id>
   <rubrik></rubrik>
   <beskrivning></beskrivning>
</element>
<element>
   <id></id>
   <rubrik></rubrik>
   <beskrivning></beskrivning>
</element>
<element>
   <id></id>
   <rubrik></rubrik>
   <beskrivning></beskrivning>
   </element>
</baselement>

Fylla elementen med värdet ur databasen

För att lägga in vårat ID-nummer, rubrik och beskrivning till respektive element använder vi oss av en ny funktion: "createTextNode".

Samma sak som tidigare gäller: Vårat XML-dokument ($xml) skapar en textsträng med hjälp av funktionen "createTextNode", men det är elementet som skall innehålla värdet som ansluter den:

$databasvarde = $xml->createTextNode($varde);
$databasvarde = $faltnamn->appendChild($databasvarde);

Nu har vi lagt till värdet från databasen till våra  taggar id, rubrik, beskrivning.

 

Skriva ut eller returnera datan i XML-dokumentet

För att vi nu skall se någon text i vårt XML-dokument så måste vi tala om för vår XML-funktion att vi är klar med inläsningen av datan och nu vill presentera resultatet.

Detta gör du genom att använda funktionen "saveXML".

$xmlstrang = $xml->saveXML();

Nu ligger hela vårt XML-dokument i variabeln "$xmlstrang".

Om du vill skriva ut datan direkt så kan du använda en vanlig "print"-funktion:

<?
print $xmlstrang;
?>

En annan lösning är att du använder variabeln "$xmlstrang" för att skriva innehållet till en fil på servern som dina samarbetspartners sen kan läsa av. Detta kan vara att rekommendera om det ofta kommer att ske förfrågningar mot ditt XML-dokument. Detta förutsätter dock att du har någon metod för att uppdatera XML-filen så fort den behöver ändras.

Ytterligare anpassning av XML-koden

Det finns fler användbara funktioner för att anpassa XML-koden. En av dessa funktioner är möjligheten att sätta attribut på ett element.

Låt oss säga att vi är kvar i exemplet med våra nyheter och vill kunna dela in nyheterna i olika kategorier.

Ett sätt att lösa detta skulle kunna vara att man skapar ett nytt element som heter "kategori" och ansluter det till varje nyhet. Det vill säga: <element><kategori>Bank & Finans</kategori>...</element>.

Detta resulterar dock snabbt i stora XML-dokument som tar tid att läsa in.

Ett snabbare och enklare sätt är att sätta ett attribut till våra nyhets-element.

Attribut fungerar på samma sätt som i HTML då man t.ex sätter ett värde till ett HTML-element: ex: <font style="font-size:12px;">

För att ansluta ett attribut till ett XML-element använder du följande kod:

$element = $xml->createElement('element');
$element = $baselement->appendChild($element);
$element->setAttribute('kategori', 'Bank & Finans');

Våra nyhetselement kommer nu att se ut på följande sätt:

<element kategori="Bank & Finans"><id>12</>...</element>

Denna lösning innehåller betydligt mindre tecken än om vi skulle skapa ett kategori-element.

 

Nu knyter vi ihop säcken med en sammanfattning 

Nu har du skapat ett grundläggande XML-dokument.

Nedanför följer en repetition av ovanstående genomgång, denna gång utan förklaringar.

Du kan även ladda ner detta exempel i en zip-fil genom denna länk.

<?
// Först ansluter vi till databasen.
if(!$dbconnect = mysql_connect('localhost', 'user', 'pass')) {
   echo "Connection failed to the host 'localhost'.";
   exit;
}
if(!mysql_select_db('test')) {
   echo "Cannot connect to database 'test'";
   exit;
}

//Vi fortsätter med att göra en databasförfrågan.
$databas = 'mintabell';
$query = "SELECT * FROM $databas";
$dbresult = mysql_query($query, $dbconnect);

// Vi skapar vårat XML-dokument
$xml = new DomDocument('1.0');

// Vi skapar ett baselement
$baselement = $xml->createElement('baselement');
$baselement = $xml->appendChild($baselement);
// Vi läser in datan från vår databasförfrågan 
while($row = mysql_fetch_assoc($dbresult)) {
 // Ett nytt element skapas för varje rad i databasen.
 $element = $xml->createElement('element');
 $element = $baselement->appendChild($element);
 // Varje rad innehåller värden, dessa lägger vi in med en foreach-loop.
 foreach($row as $namn => $varde){
  // Vi skapar ett nytt element för varje tabellfält.
  $faltnamn = $xml->createElement($namn);$faltnamn = $element->appendChild($faltnamn);
  // Värdet ur databasen läggs till under respektive fälts element
  $databasvarde = $xml->createTextNode($varde);
  $databasvarde = $faltnamn->appendChild($databasvarde);

 }
}
// Inläsningen av datan är klar. Nu genererar vi XML-dokumentet.
$xmlstrang = $xml->saveXML();
// Sist av allt, vi skriver ut dokumentet:
print $xmlstrang;
?> 

Avslutande ord

Det finns som sagt en mängd olika användningsområden för XML.

När du har lyckats få ovanstående exempel att fungera är det bara att börja experimentera på egen hand.

Om du stöter på problem så  kan du läsa mer om PHP och deras inbyggda DOM-funktioner här.