多个字符串替换

Multiple string replacements

(将问题从 'static replace' 更新为 'dynamic replace')

<data>
  <replacements>
    <replace key="greeting" value='Hello' />
    <replace key="name" value='Donald' />
  </replacements>
  <rules>
    <rule key="GREETING" value="replacements/replace[@key='greeting']/@value" />
    <rule key="NAME" value="replacements/replace[@key='name']/@value" />
  </rules>
  <text>
    GREETING NAME duck.
  </text>
</data>

我想用所有规则中每次出现的键替换元素 text 中的文本。替换文本是对该元素中属性 value 的评估。

我应该采用哪种方法(使用最新的 Saxon HE)?

文本的结果应该是“你好唐老鸭”。


加法:

我认为部分问题可以用 <xsl:evaluate> 解决,但这显然还行不通(没有字符串替换):

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0" >
  <xsl:output indent="yes"/>

  <xsl:template match="data">
    <xsl:copy>
    <xsl:evaluate xpath="/data/rules/rule[1]/@value" context-item="." />
    </xsl:copy>
  </xsl:template>
   
</xsl:stylesheet>

结果是<data value="Hello"/>。我看到的是 xpath 表达式的动态评估,从那里应该可以进行字符串替换。

现在我的步骤是将我的方法添加到 Martin 的回答中,但这将在 XPath 中混合 XSLT,这不是我想要的方式。

我不知道你在用 xsl:evaluate 做什么,如果你提到它,考虑显示你的代码,但似乎 fold-left 调用 replace 就足够了:

  <xsl:template match="text" expand-text="yes">
    <xsl:copy>{fold-left(../rules/rule, ., function($a, $r) { replace($a, $r/@key, $r/@value) })}</xsl:copy>
  </xsl:template>
  
  <xsl:template match="data/rules"/>

您可以使用更复杂的“替换规则和数据”结构

  <xsl:function name="mf:evaluate-value">
    <xsl:param name="rule" as="element(rule)"/>
    <xsl:evaluate context-item="$rule/../.." xpath="$rule/@value"/>
  </xsl:function>

  <xsl:template match="text" expand-text="yes">
      <xsl:copy>{fold-left(../rules/rule, ., function($a, $r) { replace($a, $r/@key, mf:evaluate-value($r)) })}</xsl:copy>
  </xsl:template>
  
  <xsl:template match="data/rules | data/replacements"/>

对于 use 函数,您需要在样式表中声明一个名称空间,例如xmlns:mf="http://example.com/mf".