用 xslt 替换字符串 [英] replace a string with a string with xslt

查看:36
本文介绍了用 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>

说明:

  1. 身份规则按原样"复制为其选择执行的每个匹配节点.

  1. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆