4

I have a simple PHP-based XSLT trasform code that looks like that:

$xsl = new XSLTProcessor();
$xsl->registerPHPFunctions();
$xsl->setParameter("","searchterms", $searchterms);
$xsl->importStylesheet($xslDoc);
echo $xsl->transformToXML($doc);

The code passes the variable $searchterms, which contains a string, as a parameter to the XSLT style sheet which in turns uses it as a text:

<title>search feed for <xsl:value-of select="$searchterms"/></title> 

This works fine until you try to pass a string with mixes in it, say:

$searchterms = '"some"'." text's quotes are mixed."

In that point the XSLT processor screams:

Cannot create XPath expression (string contains both quote and double-quotes)

What is the correct way to safely pass arbitrary strings as input to XSLT? Note that these strings will be used as a text value in the resulting XML and not as an XPATH paramater.

Thanks, Boaz

Boaz
  • 25,331
  • 21
  • 69
  • 77

5 Answers5

1

This has been logged as a bug:

https://bugs.php.net/bug.php?id=64137

This comment:

This shortcoming comes from the fact that XPath 1.0 does not provide a mechanism to escape characters, so PHP does not have a straightforward way to express a string that contains both types of quotes. XPath 1.0 does, however, provide a function to concatenate strings. Using concat(), a string composed of the two characters "' can be expressed as concat('"',"'"). concat() takes 2 or more arguments.

Includes the following work-around:

So as long as you alternate the quoting style, you can express a string containing any number of quotes of both types.

Another solution is to replace all straight-quotes with single-quotes:

$t = str_replace( "\"", "''", $t );
$xsltEngine->setParameter( "some-text", $t );
Dave Jarvis
  • 30,436
  • 41
  • 178
  • 315
0

if your final output is HTML you could try htmlencoding it. As long as entities are set in stylesheet should be OK

Shaun Hare
  • 3,771
  • 2
  • 24
  • 36
0

You could use &apos; to escape the single quotes:

$searchterms = '"some" text&apos;s quotes are mixed.'
Jan Willem B
  • 3,787
  • 1
  • 25
  • 39
0

This works for me to replace the single quotation marks with html special characters using str_replace

$t = str_replace("'", "&#39;", $t);  
$xsltEngine->setParameter( "some-text", $t );
Tristan
  • 3,301
  • 8
  • 22
  • 27
0

As indicated in one of the answers, this is a bug. Therefore, you can not pass both quotes.

But you can replace the double quote with another character, and then use translate to restore the original.

The main thing to choose is a character that will not appear on your text. For example \x7F.

$xsl = new XSLTProcessor();
$xsl->registerPHPFunctions();
$xsl->setParameter("","searchterms", strtr($searchterms, '"', "\x7F"));
$xsl->importStylesheet($xslDoc);
echo $xsl->transformToXML($doc);

and

<title>search feed for <xsl:value-of select="translate($searchterms, '&#x7F;', '&quot;')"/></title> 

Also, you can not use html entities, since they are being escaped.

Or use disable-output-escaping="yes":

<title>search feed for <xsl:value-of select="$searchterms" disable-output-escaping="yes"/></title> 

with

$xsl->setParameter("","searchterms", htmlspecialchars($searchterms));

The first method you can use for built-in expressions. For example:

<title attr="foo {translate($searchterms, '&#x7F;', '&quot;')} bar">bazz</title> 
Enyby
  • 4,162
  • 2
  • 33
  • 42