DOWNLOAD THE FILES FOR THIS TUTORIAL HERE
Who loves DOM programming? The answer: no one. We all know how powerful and almighty the DOM is when it comes to coding in the browser, but we also know how time consuming, confusing, and excessive it can also be. Sometimes I don’t want to rule the world like everyone else, sometimes I just want to get or change data from a basic ol’ XML file. We use simpleXML to power our totally awesome CMS system that can operate in a self contained way without a database to back it and it’s great.
I remember when I first got into experimenting with simpleXML I found a lot of the tutorials online a bit confusing, especially when it comes to learning how to edit the XML file. I’d like to try and make simpleXML simple to understand. First you have the basic task of reading some XML data. So we’re all on the same page when it comes to this, here is the XML file we’ll be working with:
guestbook.xml
<xml>
<comment time="1245429808" email="bob@bob.bob">
<who>Mr. Bill</who>
<message>Ohhhh nooooooo!</message>
</comment>
<comment time="1245429810" email="bob@bob.bob">
<who>Bob Ross</who>
<message>If you've painted, you've made mud.</message>
</comment>
</xml>
This is the outline of a very basic guest book you might have on a site. If you wanted to print all the comments and who made them, you could use this function:
READING THE XML
function getComments(){
$file = "guestbook.xml";
$xml=simplexml_load_file($file) or die("Unable to load XML!");
foreach ($xml->comment as $comment) {
echo "<strong>".$comment->who."</strong> - ";
echo $comment->message."<br><br>";
}
}
This will print:
Mr. Bill – Ohhhh nooooooo!
Bob Ross – If you’ve painted, you’ve made mud.
Simple! Now if you wanted to also make the posters name a link to their email address you could change that echo statement to this:
echo '<strong><a href="mailto:'.$comment['email'].'">';
echo $comment->who."</a></strong> - ";
echo $comment->message."<br><br>";
Adding New XML Blocks
See how easy it is to access attributes? Now, we’ll need a function to add new comments. Which would look something like this:
function newComment($name, $email, $message){
$name = htmlspecialchars($name);
$email = htmlspecialchars($email);
$message = htmlspecialchars($message);
$file = "guestbook.xml";
$xml=simplexml_load_file($file) or die("Unable to load XML!");
$time =time();
$newPage = $xml->addChild('comment');
$newPage->addAttribute('time',$time);
$newPage->addAttribute('email',$email);
$newPerson = $newPage->addChild('who',$name);
$newPage->addChild('message',$message);
file_put_contents($file, $xml->asXML());
}
To add new comments just pass the values to the function like this:
newComment("Strongbad", "strongbad@strong.com", "Ey' Steve!");
So easy!
Edit XML Data
Maybe you want to edit a comment? The function to do this is going to take advantage of the “time” attribute. The time attribute was set by php’s time() function which returns a unique time stamp, this will be our unique ID as this number will never be the same for two entries. This function will edit the tag data:
function editComment($newData, $time, $tag){
$file = "guestbook.xml";
$xml=simplexml_load_file($file) or die("Unable to load XML!");
foreach ($xml->comment as $comment) {
if($comment['time'] == $time){
$comment->$tag = htmlspecialchars($newData);
file_put_contents($file, $xml->asXML());
}
}
}
Notice how it’s a generic function? I can edit the “message” or the “who” field just by altering the parameters I pass to the function:
//change the message
editComment("email, email, email", "1245428876", "message");
//change the who
editComment("the cheat", "1245428876", "who");
Flexibility is the name of the game. With a little imagination and a lot of arrays you can even make generic functions to add new blocks of XML into a file. Thinking about looping through arrays of child elements, or multidimensional arrays of child and grandchild elements… it can get nuts.
Editing Attributes and Xpath
Now the final bit you need to know how to do is change attributes, maybe we want to change the email address of a post. I use XPath with simpleXML to do this, as I find it to be the most stable way to get it done. This last function is a doosey, these 4 little lines of code can do so much.
function writeAttribute($file, $tag, $identifier,$indenftifierVal, $attribute, $value){
$xml = simplexml_load_file($file) or die ("Unable to load XML file!");
$result = $xml->xpath('//'.$tag.'[@'.$identifier.'=\''.$indenftifierVal.'\']');
$result[0][$attribute] = $value;
file_put_contents($file, $xml->asXML());
}
The power! The power! I’m trying to cram a lot in here, so bear with me. The goal of any professional developer is to get it done correctly, and quickly. By writing versatile functions like the one above you can cycle it from one project to the next with no redevelopment time. While the other functions we’ve been going over are one time shots that would need to be tweaked to manage XML you may have elsewhere on your site, this single function can edit any XML file you’ve got anywhere on your site by just changing the way you call it. Passed to the above function you have: the XML file you want to modify, the tag in the schema (“comment” in this case), the identifier attribute (“time” in this case), the identifier value (the value of “time” in what you want to modify), the attribute you wish to change, and the value you wish it to be changed to. PHEW!
To change the email address in the Bob Ross comment you’d call the function like this:
writeAttribute("guestbook.xml","comment","time","1245429810", "email", "bob@bobross.com");
Of course there are certain XML schemes that would require the function be tweaked, but the general idea to always remember when coding functions is re-usability.
That should cover it. Till next time, keep on keepin’ on.