I am using XSLT to transform a XML into a html/php file. In this XSLT I replace some tags by php code and now I have to pass attribute values into that php code. My problem
Here's a simpler, inelegant, but quick method for replacing single quotes:
<xsl:variable name="single_quote"><xsl:text>'</xsl:text></xsl:variable>
<xsl:variable name="temp_filename" select="replace($temp_filename,$single_quote,'')"/>
1) Define a variable that contains just an apostrophe. xsl:text is required to get xsl to treat ' as a simple character
2) Use replace function using that variable as the string to match. In this example, I'm simply removing it.
Why don't you just use the standard XSLT 2.0 replace function? Or the XSLT 1.0 replace implementation xslt 1.0 string replace function
Use a recursive template to do the find/replace:
<xsl:template name="replace-string">
<xsl:param name="text"/>
<xsl:param name="replace"/>
<xsl:param name="with"/>
<xsl:choose>
<xsl:when test="contains($text,$replace)">
<xsl:value-of select="substring-before($text,$replace)"/>
<xsl:value-of select="$with"/>
<xsl:call-template name="replace-string">
<xsl:with-param name="text"
select="substring-after($text,$replace)"/>
<xsl:with-param name="replace" select="$replace"/>
<xsl:with-param name="with" select="$with"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
Applied to your example:
<xsl:template match="foo">
<xsl:processing-instruction name="php">
<xsl:text>$this->doSomething('</xsl:text>
<xsl:call-template name="replace-string">
<xsl:with-param name="text" select="./@bar"/>
<xsl:with-param name="replace" select='"'"' />
<xsl:with-param name="with" select='"\'"'/>
</xsl:call-template>
<xsl:text>');</xsl:text>
</xsl:processing-instruction>
</xsl:template>
Note:
<xsl:text>
to explicitly define text intended for the output, and not have to worry about whitespace between that text and template calls.'
for the single quote (a.k.a. apostrophe)For an XSLT 1.0 solution either write your own recursive solution, or you can use the FXSL template str-map
:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:testmap="testmap" xmlns:f="http://fxsl.sf.net/"
exclude-result-prefixes="xsl f testmap"
>
<xsl:import href="str-dvc-map.xsl"/>
<testmap:testmap/>
<xsl:variable name="vTarget">'</xsl:variable>
<xsl:variable name="vReplacement">\</xsl:variable>
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<xsl:variable name="vTestMap" select="document('')/*/testmap:*[1]"/>
<xsl:call-template name="str-map">
<xsl:with-param name="pFun" select="$vTestMap"/>
<xsl:with-param name="pStr" select="string(/*/@bar)"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="escapeApos" mode="f:FXSL"
match="*[namespace-uri() = 'testmap']">
<xsl:param name="arg1"/>
<xsl:if test="$arg1 = $vTarget">
<xsl:value-of select="$vReplacement"/>
</xsl:if>
<xsl:value-of select="$arg1"/>
</xsl:template>
</xsl:stylesheet>
When applied on the provided XML document:
<foo bar="test'xyz"/>
the wanted, correct result is produced:
test\'xyz
Just use:
$string = str_replace( "'", "\\'", $string );