0

I need to move a PHP site I inherited that uses XSLT from a server that runs PHP 5.2 to PHP 5.4. On this site the index.php script loads the XSL template, builds the XML and captures it within the output buffer. The XML is then passed to the XSLTProcessor and where the parameters are set and the HTML is printed.

$xsl = new DomDocument();
$xsl->load('xsl/homepage.xsl');
...
ob_start();
// echo XML here
$xml = ob_get_contents();
ob_end_clean();
$dom = new DomDocument();
$dom->loadXML($xml);
$dom->xinclude();
$xslt = new XSLTProcessor();
$xslt->importStylesheet($xsl);
$xslt->setParameter(null, $params);
echo $xslt->transformToXml($dom);

The problem is that on the server that runs PHP 5.4 I get a number of errors for undefined variables in the XSLT template:

Warning: XSLTProcessor::transformToXml(): runtime error: file homepage.xsl line 156 element if in index.php on line 44
Warning: XSLTProcessor::transformToXml(): Variable 'image_source' has not been declared. in index.php on line 44
...

and the HTML generation terminates there. Now, the PHP documentation (http://php.net/manual/en/xsltprocessor.transformtoxml.php) for transformToXml states that this function should return FALSE on error. However, instead it returns the partially transformed HTML.

On inspection I find that there are a number of variables defined in the XSLT template that are not present in $params, for example:

156:    <xsl:if test="$image_source!=''">
157:        <a class="slideShow">
158:            <xsl:attribute name="href"><xsl:value-of select="/root/homepage/attributes/featured_link" /></xsl:attribute>
159:            <xsl:for-each select="/root/gallery/files/file">
160:                <img class="centralColumnImage noDisplay" src="./image.php?w=460&amp;keepAspect=y&amp;img={./source}">
161:                    <xsl:if test="position() ='1'">
162:                      <xsl:attribute name="class">centralColumnImage</xsl:attribute>
163:                    </xsl:if>
164:                </img>
165:            </xsl:for-each>
166:        </a>
167:    </xsl:if>

The answer to In XSLT how do you test to see if a variable exists? states that this shouldn't work. Yet on the server that runs PHP 5.2, this code appears to at least work on that server without issue. In addition, I have checked the $params variable on the PHP 5.2 server and their contents are identical: that is, both do not have image_source nor any other variables defined that are referenced in the XSL file.

Could this be specific to PHP 5.2? I've looked in the migration guides for PHP 5.2 and PHP 5.3, and for PHP 5.3 to PHP 5.4 - yet I couldn't find backwards incompatible modifications to DOMDocument nor XSLTProcessor.

Community
  • 1
  • 1
  • Can you show the part on line 156? It appears to me that `$image_source` has simply not been declared. Perhaps a typo? As a giveaway: load the stylesheet in an XSLT editor and debugger (google, and find oXygen or others...) to spot the error directly. – Abel Sep 14 '15 at 10:08
  • @Abel sorry, it's in the original post above, I've just updated the line numbers. There are other variables other than image source which are not defined either. The trouble is that there are perhaps 100+ variables which aren't defined across the entire site. The problem I'm trying to solve is why does this work on the PHP 5.2 server despite the undefined variables? Thanks! – George Robinson Sep 14 '15 at 10:15
  • Tx in addition to this, can you also show (copy / paste from original) the line where `$image_source` is declared and whether that is globally or otherwise? – Abel Sep 14 '15 at 10:18
  • @Abel the image_source variable isn't declared anywhere in the code, globally or otherwise, same for the other variables. That's what makes this migration so frustrating. – George Robinson Sep 14 '15 at 10:30
  • Does the XSLT have an `xsl:import` or `xsl:include` statement? You should search for `name="image_source"`, not `name="$image_source"`. – Abel Sep 14 '15 at 10:33
  • @abel I did a recursive grep for image_source and found a number of matches (http://pastie.org/private/y3dgf4egq49kpkzdre9qkg). – George Robinson Sep 14 '15 at 10:44
  • As you can see in that dump, you see a commented-out `xsl:param`. Uncomment it and see what happens. Otherwise, really, just open the XSLT in an XSLT capable editor. You'll see in 5 minutes what is wrong that can take you hours this way... – Abel Sep 14 '15 at 11:43

1 Answers1

0

In the OP's pastie code, given in the comments, it was revealed that the following line existed somewhere in the XSLT (full XSLT not given, hence not possible to test):

./xsl/homepage.xsl:    <!--<xsl:param name="image_source"/>
./xsl/homepage.xsl:        <xsl:if test="$image_source!=''">

The dump did not show line numbers, nor context, so it is hard to make out whether this really is the culprit. There were 12 hits for image_source, which suggests that the name is used abundantly.

In XSLT, you can only use a name within its scope, which is typically within its containing, focus-setting container, such as xsl:template, xsl:for-each.

Abel
  • 56,041
  • 24
  • 146
  • 247