XSLT - 替换变量中的值并将结果保留为节点树
XSLT - Replace a value in a variable and keep the result as Node Tree
我知道这个问题肯定已经被问过很多次了,但这是我今天想要的一个非常具体的答案。
在我的 XSL 中,我有一个我们将命名为 "A" 的变量,它包含一个节点树,我想修改这个节点树中的一些特定值。
<xsl:variable name="A">
<node1>ABC</node1>
<node2>DEF</node2>
<node3>
<node31>ABC</node31>
<node32>DEF</node32>
</node3>
</xsl:variable>
我的这个例子的目标是用“123”替换这个节点树中每个等于 "ABC" 的值,并将结果存储在另一个变量中(因为我们无法更新值XSLT 中的变量)。
意味着我想要的结果等于:
<xsl:variable name="B">
<node1>123</node1>
<node2>DEF</node2>
<node3>
<node31>123</node31>
<node32>DEF</node32>
</node3>
</xsl:variable>
此外,变量 "B" 也必须被视为节点树。这意味着我希望有可能做 B/node1 B/node2 等...
我找到了案例,但它一次考虑了所有文档,但在我的案例中,我已经在一个变量中过滤了一个结果,并希望将其分开处理。
抱歉,我无法提供真实案例,但这是合理的数据,所以我负担不起。
允许 XSLT 2.0 或 3.0。
谢谢。
任何转换都应使用模板实现,使用单独的模式以确保处理不会干扰其余代码:
<xsl:mode name="replace-value" on-no-match="shallow-copy"/>
<xsl:param name="replacements" as="map(xs:string, xs:string)"
select="map { 'ABC' : '123' }"/>
<xsl:template match="text()[. = map:keys($replacements)]" mode="replace-value">
<xsl:value-of select="$replacements(.)"/>
</xsl:template>
<xsl:variable name="A">
<node1>ABC</node1>
<node2>DEF</node2>
<node3>
<node31>ABC</node31>
<node32>DEF</node32>
</node3>
</xsl:variable>
<xsl:variable name="B">
<xsl:apply-templates select="$A" mode="replace-value"/>
</xsl:variable>
https://xsltfiddle.liberty-development.net/ejivdHu
如果你想使用一个参数,你可以在任何 apply-templates
上更改,然后使用隧道参数并将检查移动到你想要转换的节点的模板中:
<xsl:mode name="replace-value" on-no-match="shallow-copy"/>
<xsl:param name="replacements" as="map(xs:string, xs:string)"
select="map { 'ABC' : '123' }"/>
<xsl:template match="text()" mode="replace-value">
<xsl:param name="replacements" tunnel="yes"/>
<xsl:value-of
select="if (map:contains($replacements, .))
then $replacements(.)
else ."/>
</xsl:template>
<xsl:variable name="A">
<node1>ABC</node1>
<node2>DEF</node2>
<node3>
<node31>ABC</node31>
<node32>DEF</node32>
</node3>
</xsl:variable>
<xsl:variable name="B">
<xsl:apply-templates select="$A" mode="replace-value">
<xsl:with-param name="replacements" tunnel="yes" select="$replacements"/>
</xsl:apply-templates>
</xsl:variable>
<xsl:variable name="C">
<xsl:apply-templates select="$A" mode="replace-value">
<xsl:with-param name="replacements" tunnel="yes" select="map { 'DEF' : 'xxx', 'ABC' : 'yyy' }"/>
</xsl:apply-templates>
</xsl:variable>
我知道这个问题肯定已经被问过很多次了,但这是我今天想要的一个非常具体的答案。
在我的 XSL 中,我有一个我们将命名为 "A" 的变量,它包含一个节点树,我想修改这个节点树中的一些特定值。
<xsl:variable name="A">
<node1>ABC</node1>
<node2>DEF</node2>
<node3>
<node31>ABC</node31>
<node32>DEF</node32>
</node3>
</xsl:variable>
我的这个例子的目标是用“123”替换这个节点树中每个等于 "ABC" 的值,并将结果存储在另一个变量中(因为我们无法更新值XSLT 中的变量)。
意味着我想要的结果等于:
<xsl:variable name="B">
<node1>123</node1>
<node2>DEF</node2>
<node3>
<node31>123</node31>
<node32>DEF</node32>
</node3>
</xsl:variable>
此外,变量 "B" 也必须被视为节点树。这意味着我希望有可能做 B/node1 B/node2 等...
我找到了案例,但它一次考虑了所有文档,但在我的案例中,我已经在一个变量中过滤了一个结果,并希望将其分开处理。
抱歉,我无法提供真实案例,但这是合理的数据,所以我负担不起。
允许 XSLT 2.0 或 3.0。
谢谢。
任何转换都应使用模板实现,使用单独的模式以确保处理不会干扰其余代码:
<xsl:mode name="replace-value" on-no-match="shallow-copy"/>
<xsl:param name="replacements" as="map(xs:string, xs:string)"
select="map { 'ABC' : '123' }"/>
<xsl:template match="text()[. = map:keys($replacements)]" mode="replace-value">
<xsl:value-of select="$replacements(.)"/>
</xsl:template>
<xsl:variable name="A">
<node1>ABC</node1>
<node2>DEF</node2>
<node3>
<node31>ABC</node31>
<node32>DEF</node32>
</node3>
</xsl:variable>
<xsl:variable name="B">
<xsl:apply-templates select="$A" mode="replace-value"/>
</xsl:variable>
https://xsltfiddle.liberty-development.net/ejivdHu
如果你想使用一个参数,你可以在任何 apply-templates
上更改,然后使用隧道参数并将检查移动到你想要转换的节点的模板中:
<xsl:mode name="replace-value" on-no-match="shallow-copy"/>
<xsl:param name="replacements" as="map(xs:string, xs:string)"
select="map { 'ABC' : '123' }"/>
<xsl:template match="text()" mode="replace-value">
<xsl:param name="replacements" tunnel="yes"/>
<xsl:value-of
select="if (map:contains($replacements, .))
then $replacements(.)
else ."/>
</xsl:template>
<xsl:variable name="A">
<node1>ABC</node1>
<node2>DEF</node2>
<node3>
<node31>ABC</node31>
<node32>DEF</node32>
</node3>
</xsl:variable>
<xsl:variable name="B">
<xsl:apply-templates select="$A" mode="replace-value">
<xsl:with-param name="replacements" tunnel="yes" select="$replacements"/>
</xsl:apply-templates>
</xsl:variable>
<xsl:variable name="C">
<xsl:apply-templates select="$A" mode="replace-value">
<xsl:with-param name="replacements" tunnel="yes" select="map { 'DEF' : 'xxx', 'ABC' : 'yyy' }"/>
</xsl:apply-templates>
</xsl:variable>