首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用xslt将字符串替换为字符串

使用xslt将字符串替换为字符串
EN

Stack Overflow用户
提问于 2012-09-11 07:19:42
回答 3查看 8.7K关注 0票数 3

我想用另一个字符串替换另一个字符串。我找到了一个这样做的例子,但似乎不起作用。这是一个示例数据

代码语言:javascript
运行
复制
<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>

我想用这种方式替换下面的字符串。

代码语言:javascript
运行
复制
 Dwelling = FLAT
 Lodge    =  SHOP

下面是我使用的代码。它只删除了LD元素中的所有值。

代码语言:javascript
运行
复制
<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>

如果应用于上面的输入数据,它会产生以下结果:

代码语言:javascript
运行
复制
   <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>

使用适当的代码应产生预期结果

代码语言:javascript
运行
复制
   <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>  
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-09-11 13:12:04

这里的是一个用于执行多个字符串替换的XSLT转换--不需要扩展函数

代码语言:javascript
运行
复制
<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文档上应用此转换时的

代码语言:javascript
运行
复制
<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>

生成所需的正确结果:

代码语言:javascript
运行
复制
<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文档时,比较两种解决方案的结果

代码语言:javascript
运行
复制
<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的解决方案产生不正确的替换

代码语言:javascript
运行
复制
<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>

回答来自的当前正确的解决方案,生成正确的替代方案:

代码语言:javascript
运行
复制
<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.

  • It
  1. 标识规则原样复制为LD选择的每个匹配节点都会被与任何

元素的任何文本节点子代匹配的单个模板覆盖。

  1. 此模板检查匹配的文本节点是否包含全局内联my:reps元素中指定的任何old (字符串值)。为方便起见,在名为$vReps的全局变量中选择了所有my:reps/rep元素,并从该变量中引用了这些元素。如果这些字符串都不包含在当前节点中,则将其复制到output。
  2. 如果至少有一个$vReps/old元素的字符串值包含在当前匹配的文本节点中,则必须进行替换。我们调用一个名为"multiReplace"的模板,该模板执行当前文本节点中的所有替换。我们将当前文本节点和所有$vReps/rep元素的节点集作为参数传递给该模板--这些都是要进行的替换操作。
  3. multiReplace模板调用名为singleReplace的模板进行第一次替换,并在名为$vRepResult的变量中捕获结果。这包含在$pText中将所有出现的$pReps[1]/old (的字符串值)替换为$pReps[1]/new的字符串值的结果。然后,multiReplace模板使用到目前为止作为$pText参数传递的替换结果和要进行的替换节点集(第一个替换被排除在外)递归地调用自身--作为$pReps参数。这种递归的“停止条件”是,当$pReps参数变为空的node-set.
  4. The singleReplace模板时,它会如其名称所示--在其$pText参数中包含的字符串中,将等于$pOld参数的任何子字符串替换为pNew参数中包含的字符串。替换的数量可能大于1,但所有替换都是针对单个替换规范==>的,因此名称为singleReplace。当$pText为非空且仍包含$pOld.

时,将再次以递归方式使用stop条件进行替换

票数 2
EN

Stack Overflow用户

发布于 2012-09-11 07:58:54

现有代码的问题是这一行

代码语言:javascript
运行
复制
<xsl:value-of select="$lookup/LD[@code = current()]" />

只有当有一个LD元素的文本等于上下文节点的整个文本时,才会发出任何内容。因此,谓词需要使用contains()而不是=

使用XSLT 2.0,您可以按如下方式更改此模板:

代码语言:javascript
运行
复制
<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()节点中不会出现超过一段代码。

票数 0
EN

Stack Overflow用户

发布于 2012-09-11 10:00:33

LarsH的解决方案是一个很好的方案。如果支持EXSLT,请尝试使用它。如果不支持,并且您的XSLT引擎是Microsoft,则此XSLT 1.0样式表...

代码语言:javascript
运行
复制
<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应用于此输入...

代码语言:javascript
运行
复制
<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>

..。收益率...

代码语言:javascript
运行
复制
<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,则使用此样式表...

代码语言:javascript
运行
复制
<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>
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12360735

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档