Entities are omitted from the output with the code above.
The symptom was that
-- which should work with UTF-8 encoding --
did not even get to XSLTProcessor, let alone through it.
After too much hacking I discovered the simple fix:
set substituteEntities to true in the DOMDocument for the XSL file.
That is, replace the loading of the xsl document with
<?php
$xsl = new DOMDocument;
$xsl->substituteEntities = true; $xsl->load('collection.xsl');
?>
However, this fails when data entries have HTML entity references. (Some database entries may even contain user generated text.) libxml has the pedantic habit of throwing a FATAL error for any undefined entitiy. Solution: hide the entities so libxml doesn't see them.
<?php
function hideEntities($data) {
return str_replace("&", "&", $data);
}
?>
You could just add this to the example, but it is tidier to define a function to load data into a DOMDocument. This way you don't need entity declarations in catalog.xsl, either.
<?php
function fileToDOMDoc($filename) {
$dom= new DOMDocument;
$xmldata = file_get_contents($filename);
$xmldata = str_replace("&", "&", $xmldata); $dom->substituteEntities = true; $dom->loadXML($xmldata);
return $dom;
}
$xml = fileToDOMDoc('collection.xml');
$xsl = fileToDOMDoc('collection.xsl');
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl);
echo $proc->transformToXML($xml); ?>