XSLT: заменить одиночные кавычки на \

Я использую XSLT для преобразования XML в файл html / php. В этом XSLT я заменяю некоторые теги php-кодом, и теперь мне нужно передать значения атрибутов в этот php-код. Моя проблема заключается в том, что мне нужно избегать одиночных кавычек с обратной косой чертой, чтобы заставить ее работать. Возможно ли это с XSLT.

Пример:

<xsl:template match="foo"> <xsl:processing-instruction name="php">$this->doSomething('<xsl:value-of select="./@bar" />');</xsl:processing-instruction> </xsl:template> 

Если у меня теперь был шаблон:

 <foo bar="test'xyz"/> 

Это создаст:

 <?php $this->doSomething('test'xyz');?> 

Теперь я хочу добиться следующего:

 <?php $this->doSomething('test\'xyz');?> 

Поэтому я хочу заменить все одинарные кавычки на \

Используйте рекурсивный шаблон для поиска / замены:

 <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> в <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> в <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> 

Применяется к вашему примеру:

  <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='"&apos;"' /> <xsl:with-param name="with" select='"\&apos;"'/> </xsl:call-template> <xsl:text>');</xsl:text> </xsl:processing-instruction> </xsl:template> 

Заметка:

  1. Использование <xsl:text> для явного определения текста, предназначенного для вывода, и не нужно беспокоиться о пробеле между этими текстами и вызовами шаблона.
  2. Использование одинарных кавычек для включения оператора select для замены и с параметрами, чтобы использовать двойные кавычки для указания текстового оператора, содержащего одиночную кавычку
  3. Использование ссылки на сущность для одиночной цитаты (ака-апострофа)

Почему бы вам просто не использовать стандартную функцию замены XSLT 2.0? Или XSLT 1.0 заменит реализацию xslt 1.0 string replace function

Для решения XSLT 1.0 либо пишите свое собственное рекурсивное решение, либо вы можете использовать шаблонную карту шаблона FXSL :

 <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> 

При применении к предоставленному XML-документу :

 <foo bar="test'xyz"/> 

получается желаемый, правильный результат :

 test\'xyz 

Просто используйте:

 $string = str_replace( "'", "\\'", $string );