用 xslt 替换字符串 [英] replace a string with a string with xslt
问题描述
我想用另一个字符串替换一个字符串.我找到了一个这样做的例子,但似乎没有用.这是一个示例数据
i want to replace a string with another string. i found an example that does that but didnt seem to work. this is a sample data
<Addy>
<Row>
<LD>Dwelling, 1</D>
<LN> East</LN>
<L>1</L>
<Tf>Abesinia Passage</Tf>
</Row>
<Row>
<LD>Logde</LD>
<LN>North </LN>
<L>1</L>
<Tf>Abesinia Passage</Tf>
</Row>
</Addy>
我想以这种方式替换以下字符串.
i want to replace the following string in this manner.
Dwelling = FLAT
Lodge = SHOP
以下是我使用的代码.它只删除了 LD 元素中的所有值.
Below are the codes i used. it only deleted all the values in LD element.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:lookup="lookup">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<lookup:data>
<LD code="Dwelling">FLAT</LD>
<LD code="Lodge">SHOP</LD>
</lookup:data>
<xsl:variable name="lookup" select="document('')/*/lookup:data"/>
<xsl:template match="LD/text()">
<xsl:value-of select="$lookup/LD[@code = current()]" />
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
如果应用于上面的输入数据,它会产生:
If applied to the input data above, it produces this:
<Addy>
<Row>
<LD></LD>
<LN> East</LN>
<L>1</L>
<Tf>Abesinia Passage</Tf>
</Row>
<Row>
<LD></LD>
<LN>North </LN>
<L>1</L>
<Tf>Abesinia Passage</Tf>
</Row>
</Addy>
应产生适当代码的预期结果
expected result with appropriate codes should produce
<Addy>
<Row>
<LD>FLAT,1</D>
<LN> East</LN>
<L>1</L>
<Tf>Abesinia Passage</Tf>
</Row>
<Row>
<LD>SHOP</LD>
<LN>North </LN>
<L>1</L>
<Tf>Abesinia Passage</Tf>
</Row>
</Addy>
推荐答案
这里是一个 XSLT 转换,用于对字符串执行多次替换——不需要扩展函数:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="my:my">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<my:reps>
<rep>
<old>Dwelling</old>
<new>FLAT</new>
</rep>
<rep>
<old>Lodge</old>
<new>SHOP</new>
</rep>
</my:reps>
<xsl:variable name="vReps" select="document('')/*/my:reps/*"/>
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="LD/text()" name="replace">
<xsl:param name="pText" select="."/>
<xsl:choose>
<xsl:when test="not($vReps/old[contains($pText, .)])">
<xsl:value-of select="$pText"/>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="multiReplace">
<xsl:with-param name="pText" select="$pText"/>
<xsl:with-param name="pReps"
select="$vReps[contains($pText, old)]"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="multiReplace">
<xsl:param name="pText"/>
<xsl:param name="pReps"/>
<xsl:choose>
<xsl:when test="$pReps">
<xsl:variable name="vRepResult">
<xsl:call-template name="singleReplace">
<xsl:with-param name="pText" select="$pText"/>
<xsl:with-param name="pOld" select="$pReps[1]/old"/>
<xsl:with-param name="pNew" select="$pReps[1]/new"/>
</xsl:call-template>
</xsl:variable>
<xsl:call-template name="multiReplace">
<xsl:with-param name="pText" select="$vRepResult"/>
<xsl:with-param name="pReps" select="$pReps[position() >1]"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$pText"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="singleReplace">
<xsl:param name="pText"/>
<xsl:param name="pOld"/>
<xsl:param name="pNew"/>
<xsl:if test="$pText">
<xsl:choose>
<xsl:when test="not(contains($pText, $pOld))">
<xsl:value-of select="$pText"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="substring-before($pText, $pOld)"/>
<xsl:value-of select="$pNew"/>
<xsl:call-template name="singleReplace">
<xsl:with-param name="pText" select="substring-after($pText, $pOld)"/>
<xsl:with-param name="pOld" select="$pOld"/>
<xsl:with-param name="pNew" select="$pNew"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
当此转换应用于提供的 XML 文档时:
<Addy>
<Row>
<LD>Dwelling, 1</LD>
<LN> East</LN>
<L>1</L>
<Tf>Abesinia Passage</Tf>
</Row>
<Row>
<LD>Lodge</LD>
<LN>North </LN>
<L>1</L>
<Tf>Abesinia Passage</Tf>
</Row>
</Addy>
产生了想要的、正确的结果:
<Addy>
<Row>
<LD>FLAT, 1</LD>
<LN> East</LN>
<L>1</L>
<Tf>Abesinia Passage</Tf>
</Row>
<Row>
<LD>SHOP</LD>
<LN>North </LN>
<L>1</L>
<Tf>Abesinia Passage</Tf>
</Row>
</Addy>
重要:
此解决方案是完整且正确的.肖恩说的很肤浅.
This solution is complete and correct. Sean's is rather superficial.
比较两种解决方案在应用于以下 XML 文档时的结果:
<Addy>
<Row>
<LD>Dwelling, Lodge, 1</LD>
<LN> East</LN>
<L>1</L>
<Tf>Abesinia Passage</Tf>
</Row>
<Row>
<LD>Lodge, Dwelling</LD>
<LN>North </LN>
<L>1</L>
<Tf>Abesinia Passage</Tf>
</Row>
</Addy>
Sean 的解决方案产生了不正确的替换:
<Addy>
<Row>
<LD>FLAT, Lodge, 1</LD>
<LN> East</LN>
<L>1</L>
<Tf>Abesinia Passage</Tf>
</Row>
<Row>
<LD>Lodge, FLAT</LD>
<LN>North </LN>
<L>1</L>
<Tf>Abesinia Passage</Tf>
</Row>
</Addy>
来自这个答案的当前正确解决方案产生了正确的替换:
The current, correct solution from this answer, produces the correct replacements:
<Addy>
<Row>
<LD>FLAT, SHOP, 1</LD>
<LN> East</LN>
<L>1</L>
<Tf>Abesinia Passage</Tf>
</Row>
<Row>
<LD>SHOP, FLAT</LD>
<LN>North </LN>
<L>1</L>
<Tf>Abesinia Passage</Tf>
</Row>
</Addy>
说明:
身份规则按原样"复制为其选择执行的每个匹配节点.
The identity rule copies "as is" every matching node for which it is selected for executiom.
它被与任何 LD
元素的任何文本节点子节点匹配的单个模板覆盖——必须在其中进行替换的节点.
It is overriden by a single template matching any text-node child of any LD
element -- the nodes in which replacements must be done.
此模板检查匹配的文本节点是否包含任何 old
(字符串值),如全局内联 my:reps
元素中指定的那样.为方便起见,所有 my:reps/rep
元素都已在名为 $vReps
的全局变量中选择,并从该变量中引用.如果当前节点中不包含这些字符串中的任何一个,则将其复制到输出中.
This template checks if the matched text node contais any of the old
(string values), as specified in the global inline my:reps
element. For convenience all my:reps/rep
elements have been selected in a global variable named $vReps
and are referenced off this variable. If none of these strings are contained in the current node, then it is copied to the output.
如果至少有一个 $vReps/old
元素的字符串值包含在当前匹配的文本节点中,那么我们必须进行替换.我们调用一个名为 "multiReplace"
的模板,它在当前文本节点中执行所有替换.我们将当前文本节点和所有 $vReps/rep
元素的节点集作为参数传递给该模板,其 old
子元素的字符串值包含在当前文本节点中 -- 这些都是要进行的替换.
If there is at least one $vReps/old
element whose string value is contained in the currently matched text node, then we must do replacements. We call a template with name "multiReplace"
that performs all replacements in the current text node. We pass to this template as parameters the current text node and a nodeset of all $vReps/rep
elements the string value of whose old
child is contained in the current text node -- these are all the replacements to be made.
multiReplace
模板调用名为 singleReplace
的模板进行第一次替换并将结果捕获到名为 $vRepResult
的变量中.这包含在 $pText
所有 出现的(字符串值)$pReps[1]/old
替换为字符串值的结果$pReps[1]/new
.然后,multiReplace
模板递归调用自身,使用到目前为止作为 $pText
参数传递的替换结果,以及要进行的替换节点集,其中第一个替换被排除——作为 $pReps
参数.此递归的停止条件"是 $pReps
参数变为空节点集时.
The multiReplace
template calls a template named singleReplace
to do the first replacement and captures the result in a variable named $vRepResult
. This contains the result of replacing in $pText
all occurences of (the string value of) $pReps[1]/old
with the string value of $pReps[1]/new
. Then the multiReplace
template calls itself recursively with the result of the replacements so far passed as the $pText
parameter, and the node-set of replacements to be made from which the first replacement is excluded -- as the $pReps
parameter. The "stop-condition" for this recursion is when the $pReps
parameter becomes the empty node-set.
singleReplace
模板按其名称执行操作——它替换包含在其 $pText
参数中的字符串中与 $ 相同的任何子字符串pOld
参数和 pNew
参数中包含的字符串.替换的数量可能大于 1,但它们都是针对单个替换规范 ==> 因此名称 singleReplace
.当 $pText
非空且仍包含 $pOld
时,替换再次以递归方式完成,并带有停止条件.
The singleReplace
template does what it name says -- it replaces in the string contained in its $pText
parameter any substring equal to the $pOld
parameter with the string contained in the pNew
parameter. The number of replacements may be greater than one, but all of them are for a single replacement specification ==> thus the name singleReplace
. The replacements are again done in a recursive manner with stop condition when $pText
is non-empty and still contains $pOld
.
这篇关于用 xslt 替换字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!