我想用另一个字符串替换另一个字符串。我找到了一个这样做的例子,但似乎不起作用。这是一个示例数据
<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>我想用这种方式替换下面的字符串。
Dwelling = FLAT
Lodge = SHOP下面是我使用的代码。它只删除了LD元素中的所有值。
<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>如果应用于上面的输入数据,它会产生以下结果:
<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>使用适当的代码应产生预期结果
<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> 发布于 2012-09-11 13:12:04
这里的是一个用于执行多个字符串替换的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>重要
这个解决方案是完整和正确的。肖恩的很肤浅。
当应用于下面的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>回答来自的当前正确的解决方案,生成正确的替代方案:
<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>说明
executiom.
LD选择的每个匹配节点都会被与任何元素的任何文本节点子代匹配的单个模板覆盖。
my:reps元素中指定的任何old (字符串值)。为方便起见,在名为$vReps的全局变量中选择了所有my:reps/rep元素,并从该变量中引用了这些元素。如果这些字符串都不包含在当前节点中,则将其复制到output。$vReps/old元素的字符串值包含在当前匹配的文本节点中,则必须进行替换。我们调用一个名为"multiReplace"的模板,该模板执行当前文本节点中的所有替换。我们将当前文本节点和所有$vReps/rep元素的节点集作为参数传递给该模板--这些都是要进行的替换操作。multiReplace模板调用名为singleReplace的模板进行第一次替换,并在名为$vRepResult的变量中捕获结果。这包含在$pText中将所有出现的$pReps[1]/old (的字符串值)替换为$pReps[1]/new的字符串值的结果。然后,multiReplace模板使用到目前为止作为$pText参数传递的替换结果和要进行的替换节点集(第一个替换被排除在外)递归地调用自身--作为$pReps参数。这种递归的“停止条件”是,当$pReps参数变为空的node-set.singleReplace模板时,它会如其名称所示--在其$pText参数中包含的字符串中,将等于$pOld参数的任何子字符串替换为pNew参数中包含的字符串。替换的数量可能大于1,但所有替换都是针对单个替换规范==>的,因此名称为singleReplace。当$pText为非空且仍包含$pOld.时,将再次以递归方式使用stop条件进行替换
发布于 2012-09-11 07:58:54
现有代码的问题是这一行
<xsl:value-of select="$lookup/LD[@code = current()]" />只有当有一个LD元素的文本等于上下文节点的整个文本时,才会发出任何内容。因此,谓词需要使用contains()而不是=。
使用XSLT 2.0,您可以按如下方式更改此模板:
<xsl:template match="LD/text()">
<xsl:variable name="LD" select="$lookup/LD[contains(current(), @code)]" />
<xsl:value-of select="replace(., $LD/@code, $LD/text())" />
</xsl:template>如果不能使用XSLT2.0,可以使用EXSLT str:replace()而不是XSLT2.0版本。
这假设code属性值不包含任何在正则表达式中会被特殊解释的特殊字符,如.、$等。
它还假设任何LD/text()节点中不会出现超过一段代码。
发布于 2012-09-11 10:00:33
LarsH的解决方案是一个很好的方案。如果支持EXSLT,请尝试使用它。如果不支持,并且您的XSLT引擎是Microsoft,则此XSLT 1.0样式表...
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:l="http://stackoverflow.com/questions/12360735"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
exclude-result-prefixes="xsl l msxsl" >
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="lookup">
<l:map pattern="Dwelling" replacement="FLAT" />
<l:map pattern="Lodge" replacement="SHOP" />
</xsl:variable>
<xsl:template match="LD/text()">
<xsl:choose>
<xsl:when test="contains(.,msxsl:node-set($lookup)/l:map/@pattern)">
<xsl:variable name="hay-stack" select="." />
<xsl:for-each select="(msxsl:node-set($lookup)/l:map[contains($hay-stack,@pattern)])[1]">
<xsl:value-of select="concat(
substring-before($hay-stack,@pattern),
@replacement,
substring-after($hay-stack,@pattern))" />
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="." />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>...when应用于此输入...
<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>Lodge</LD>
<LN>North </LN>
<L>1</L>
<Tf>Abesinia Passage</Tf>
</Row>
</Addy>如果不是Microsoft,并且您不能使用EXSLT,则使用此样式表...
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:l="http://stackoverflow.com/questions/12360735"
exclude-result-prefixes="xsl l" >
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="lookup">
<l:map pattern="Dwelling" replacement="FLAT" />
<l:map pattern="Lodge" replacement="SHOP" />
</xsl:variable>
<xsl:template match="LD/text()">
<xsl:choose>
<xsl:when test="contains(.,document('')/*/xsl:variable[@name="lookup"]/l:map/@pattern)">
<xsl:variable name="hay-stack" select="." />
<xsl:for-each select="(document('')/*/xsl:variable[@name="lookup"]/l:map[contains($hay-stack,@pattern)])[1]">
<xsl:value-of select="concat(
substring-before($hay-stack,@pattern),
@replacement,
substring-after($hay-stack,@pattern))" />
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="." />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>https://stackoverflow.com/questions/12360735
复制相似问题