Я закончил тем, что делал что-то вроде этого:
<!-- Reusable template to perform substitutions on a string -->
<xsl:template name="substitutions">
<!-- "string" is a string with placeholders surrounded by {} -->
<xsl:param name="string" />
<!-- "subs" is a list of nodes whose "key" attributes are the placeholders -->
<xsl:param name="subs" />
<xsl:analyze-string select="$string" regex="\{{(.*?)\}}">
<xsl:matching-substring>
<xsl:value-of select="$subs/sub[@key=regex-group(1)]" />
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="." />
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:template>
<!-- Example use of template -->
<xsl:variable name="nameStr">My name is {name} and my age is {age}</xsl:variable>
<xsl:call-template name="substitutions">
<xsl:with-param name="string" select="$nameStr" />
<xsl:with-param name="subs">
<sub key="name">Joe</sub>
<sub key="age">50</sub>
</xsl:with-param>
</xsl:call-template>
Мне пришлось использовать атрибуты для имен замещения, а не просто передавать узлы с разными именами (например, Джо ). XPath (или, по крайней мере, Saxon, процессор, который я использую), по-видимому, не допускает динамических выражений типа «$ subs / regex-group (1)». Но он допускает «$ subs / sub [@ key = regex-group (1)]».