How to use XSLT with PHP (very simply)
Using XSLT with PHP is very easy to do — but you will need to check you have the right modules installed. Lets take a quick look.
Installing PHP and the checking for XML module support
XSLT is well supported within PHP but will need to install PHP first.
PHP isn’t available upon opening the browser the way that Javascript is available within the browser without any installation and of course requires being served from a local or online server.
The advantage of using PHP with XSLT is that the transformation is completed server side, so will show the user the transformation regardless of what browser they are using.
In Linux, download PHP via the terminal:
sudo apt-get install php
It’s useful to check your PHP version — mine has come out as 7.2
php -v
If you download PHP via the terminal in Linux you might find the XML modules are not downloaded.
You can check whether these are installed with:
php -i | grep "xml"
Or you can check the modules installed:
php -m
If this doesn’t list the below modules you won’t be able to use XSLT or indeed SimpleXML, XMLReader, XMLWriter.
SimpleXML
...
xml
xmlreader
xmlwriter
xsl
To install these, try this:
sudo apt-get install php-xml
You can also check the version of libXML. LibXML is the lower level library support for handling XML and PHP relies upon this for error checking.
php --ri libxml
...
libxml
libXML support => active
libXML Compiled Version => 2.9.4
libXML Loaded Version => 20904
libXML streams => enabled
You can also check the string ‘xml’ with the above to check:
php --ri xml
...
XML Support => active
XML Namespace Support => active
libxml2 Version => 2.9.4
On distros that use Yum, you can try the below:
sudo yum -y install php-xml
If you are using Apache2 then you will need to restart after making these changes to ensure they have taken effect e.g.
sudo service apache2 restart
Example of using DOMDocument and XSLTProcessor
You might have seen references to xslt_create(); etc these are older methods in PHP 5.6, the modern method to process XSLT is XSLTProcessor();
To use this you have to load XML and XSLT first through the use of DOMDocument(); and then use the importStyleSheet method to load the stylesheet.
Lastly, the transformToXML method performs the XSLT transformation.
These methods are not dissimilar to the counterpart methods in Javascript.
<?php
$xsl = "data/example.xsl";
$xml = "data/example.xml";
$xmldoc = new DOMDocument();
$xsldoc = new DOMDocument();
$xslproc = new XSLTProcessor();
if (file_exists($xml)){
if(!$xmldoc->load($xml)){
echo "could not load xml documents";
}
}
if (file_exists($xsl)){
if(!$xsldoc->load($xsl)){
echo "could not load xsl documents";
}
}
libxml_use_internal_errors(true);
$result = $xslproc->importStyleSheet($xsldoc);
if (!$result) {
foreach (libxml_get_errors() as $error) {
echo "Libxml error: {$error->message}\n";
}
}
libxml_use_internal_errors(false);
if ($result) {
echo $xslproc->transformToXML($xmldoc);
}
?>
Example of using SimpleXML to load the XML and XSL files
SimpleXML is a popular way to deal with XML files and is easier to use than DOM methods.
SimpleXML provides the simplexml_load_file(); function to load XML files.
We can then use the XSLTProcessor(); and transformToXML method to apply the transformation.
<?php
$xsl = "data/example.xsl";
$xml = "data/example.xml";
$xmldoc = new DOMDocument();
$xsldoc = new DOMDocument();
$xslproc = new XSLTProcessor();
if (file_exists($xml)){
$xmldoc = simplexml_load_file($xml);
}
if (file_exists($xsl)){
$xsldoc = simplexml_load_file($xsl);
}
libxml_use_internal_errors(true);
$result = $xslproc->importStyleSheet($xsldoc);
if (!$result) {
foreach (libxml_get_errors() as $error) {
echo "Libxml error: {$error->message}\n";
}
}
libxml_use_internal_errors(false);
if ($result) {
echo $xslproc->transformToXML($xmldoc);
}
?>
Using PHP and Javascript to transform XSLT
You can of course use Javascript and PHP together to transform XSLT on the web — this is not something that my previous posts have looked at but using both these languages together gives:
- The benefit of asynchronous nature of Javascript
- Offloading the XSLT transformation to PHP rather that performing the XSLT transformation through Javascript.
Of course the “benefit” in the real-world depends on how these languages are used.
This example uses jQuery $.get() to call the PHP file. (You could of course use old-fashioned XMLHttpRequest, Async/Await with the Fetch API to do exactly the same).
The PHP file then performs the XSLT transformation and the output is returned and the nodes are appended to <div id=”example”></div>
$.get("XSLT.php", function(data) {
$("#example").append(data);
});
This below jQuery example using $.ajax() won't work, this is because - at least in Firefox - a <meta> element is included in the output and is left open, like so:
<meta http-equiv=”Content-Type” content=”text/html; charset=UTF-8">
As this element is not closed, $.ajax() recognises this element as inproper XML.
$.ajax({
type:"GET",
url: "Example9-XSLT.php",
dataType: "xml",
success: function (data) {
$("#example").append(data);
}
});
Note you can change the dataType to "text", but the <meta> remains.
$.ajax({
type: "GET",
url: "Example9-XSLT.php",
dataType: "text",
success: function (data) {
$("#example").append(data);
}
});
You can also use the more modern fetch() API — as I’ve covered in other recent posts in XSLT for the Modern Web:
- Using jQuery with XSLT — .ajax(), .ajax() with Promises, .get()
- XSLT with Fetch() API — modern Javascript with/without Async and Await
- Using Javascript Promise.allSettled() to apply multiple XSLT transformations
fetch("Example9-XSLT.php").then(function(response){
if(response){
return response.text();
}
}).then(function(data) {
$("#example").append(data);
})
.catch(function(error) {
console.log('Looks like there was a problem: ', error);
});
Further example — using XSLT parameters
Here is a more complex example of using PHP and Javascript to apply a XSLT transformation, but also using passing a parameter to the XSLT stylesheet to present only particular books of Herodotus’ Histories.
Books are selected from a drop-down list.
Here is the HTML first (intentionally simplified).
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>XSLT</title>
<script type="text/javascript" src="jquery-3.6.0.min.js"></script>
</head>
<body>
<h2>Book</h2>
<form>
<select>
<option value="1">Book 1</option>
<option value="2">Book 2</option>
<option value="3">Book 3</option>
<option value="4">Book 4</option>
<option value="5">Book 5</option>
</select>
</form>
<div id="example">
</div>
<script type="text/javascript">
$(function(){
$("select").on('change', function(){
//in the real-world you would sense check this value and sanitise
let bookVal = this.value;
$.get("XSLT.php", { book: bookVal }, function(data) {
//empty the <div> to remove any existing content
$("#example").empty();
$("#example").append(data);
});
});
});
</script>
</body>
</html>
Here is the PHP — XSLT.php.
(The XML file I am using within this example is Herodotus’ The Histories from the Perseus Digital Library website. Perseus makes this text available under a Creative Commons Attribution-ShareAlike 3.0 United States License.
This version of The Histories is an an English translation by A. D. Godley. Cambridge. Harvard University Press. 1920. The Histories is a good example to use as it includes mention of a range of persons, events, places, notes and anecdotes. The edition by Godley also includes many notes which add to the richness of a read.)
I am using this line to get the value assiged to ‘book’ GET request $book = htmlspecialchars($_GET[“book”]); and using this line to set the <xs:param> value book in my XSLT stylesheet:
$xslproc->setParameter(‘’, ‘book’, $book);
<?php
$xsl = "data/example-10.xsl";
$xml = "data/Perseus_text_1999.01.0126.xml";
$xmldoc = new DOMDocument();
$xsldoc = new DOMDocument();
$xslproc = new XSLTProcessor();
$book = htmlspecialchars($_GET["book"]);
if (file_exists($xml)){
$xmldoc = simplexml_load_file($xml);
}else{
echo "could not load xml document";
}
if (file_exists($xsl)){
$xsldoc = simplexml_load_file($xsl);
}else{
echo "could not load xsl document";
}
libxml_use_internal_errors(true);
$xslproc->setParameter('', 'book', $book);
$result = $xslproc->importStyleSheet($xsldoc);
if (!$result){
foreach (libxml_get_errors() as $error){
echo "Libxml error: {$error->message}\n";
}
}
libxml_use_internal_errors(false);
if ($result){
echo $xslproc->transformToXML($xmldoc);
}
?>
Finally, here is the XSLT stylesheet which has been adapted to progress templates on the basis of Book number. There are other ways of achieving the same result, this is just an example.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:param name="book" select="1"/>
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="div1[@type='Book']">
<xsl:if test="@n = $book">
<h2>Book <xsl:value-of select="$book"/></h2>
<xsl:apply-templates/>
</xsl:if>
</xsl:template>
<xsl:template match="teiHeader"/>
</xsl:stylesheet>
Want to learn more about using XSLT on the web in a simple way? Why not check out one of these recent posts next?
- Beginners XSLT patterns explained — simple key lookup
- What is XSLT and is it still relevant in a website context in 2024?
- XSLT in the web browser — simple transformations on the server
- Using jQuery with XSLT — .ajax(), .ajax() with Promises, .get()
- XSLT with Fetch() API — modern Javascript with/without Async and Await
- Using Javascript Promise.allSettled() to apply multiple XSLT transformations
- Beginners XSLT patterns explained — simple key lookup
- Beginners XSLT patterns explained — lookup without <xsl:key>, using XPath
- Beginners XSLT patterns explained — simple key lookup
- Beginners XSLT patterns explained — lookup without <xsl:key>, using XPath