使用xslt替换xml中的文本

时间:2010-12-14 05:11:33

标签: xslt

我有一个XML文件,它在子元素和属性中都有一些值。 如果我想在匹配特定值时替换某些文本,我该如何实现呢? 我尝试使用xlst:translate()函数。但我不能将此函数用于xml中的每个元素或属性。 那么无论如何都要一次性替换/翻译价值?

<?xml version="1.0" encoding="UTF-8"?>
<Employee>
 <Name>Emp1</Name>
 <Age>40</Age>
 <sex>M</sex>
 <Address>Canada</Address> 
 <PersonalInformation>
   <Country>Canada</country>
   <Street1>KO 92</Street1>   
 </PersonalInformation>
</Employee>

输出:

<?xml version="1.0" encoding="UTF-8"?>
<Employee>
 <Name>Emp1</Name>
 <Age>40</Age>
 <sex>M</sex>
 <Address>UnitedStates</Address> 
 <PersonalInformation>
   <Country>UnitedStates</country>
   <Street1>KO 92</Street1>   
 </PersonalInformation>
</Employee>

在输出中,将文本从加拿大替换为美国。 因此,如果不对任何元素使用xslt:transform()函数,我应该能够将文本Canada替换为UnitedStates,而不管级别节点如何。 无论我在哪里找到'加拿大',我都应该能够在整个xml中替换为'UnitedStates'。 那我怎么能实现这个目标呢?

1 个答案:

答案 0 :(得分:4)

予。 XSLT 1.0解决方案:

此转化:

<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>replace this</old>
    <new>replaced</new>
  </rep>
  <rep>
    <old>cat</old>
    <new>tiger</new>
  </rep>
 </my:Reps>

 <xsl:variable name="vReps" select=
  "document('')/*/my:Reps/*"/>

 <xsl:template match="node()|@*" name="identity">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="@*">
  <xsl:attribute name="{name()}">
   <xsl:call-template name="replace">
    <xsl:with-param name="pText" select="."/>
   </xsl:call-template>
  </xsl:attribute>
 </xsl:template>

 <xsl:template match="text()" name="replace">
  <xsl:param name="pText" select="."/>
   <xsl:if test="string-length($pText)">
     <xsl:choose>
       <xsl:when test=
        "not($vReps/old[contains($pText, .)])">
         <xsl:copy-of select="$pText"/>
       </xsl:when>
       <xsl:otherwise>
         <xsl:variable name="vthisRep" select=
         "$vReps/old[contains($pText, .)][1]
         "/>

         <xsl:variable name="vNewText">
           <xsl:value-of
            select="substring-before($pText, $vthisRep)"/>
           <xsl:value-of select="$vthisRep/../new"/>
           <xsl:value-of select=
            "substring-after($pText, $vthisRep)"/>
         </xsl:variable>

         <xsl:call-template name="replace">
           <xsl:with-param name="pText"
            select="$vNewText"/>
         </xsl:call-template>
       </xsl:otherwise>
     </xsl:choose>
   </xsl:if>
 </xsl:template>
</xsl:stylesheet>

应用于此XML文档时

<t>
 <a attr1="X replace this Y">
   <b>cat mouse replace this cat dog</b>
 </a>
 <c/>
</t>

生成想要的正确结果

<t>
   <a attr1="X replaced Y">
      <b>tiger mouse replaced tiger dog</b>
   </a>
   <c/>
</t>

<强>解释

  1. 使用身份规则复制“按原样”某些节点。

  2. 我们执行多次替换,在my:Reps

  3. 中进行参数化
  4. 如果文本节点或属性不包含任何rep-target,则按原样复制

  5. 如果文字节点或属性包含要替换的文字(代表目标),则替换按照my:Reps中指定的顺序完成

  6. 如果字符串包含多个字符串目标,则替换所有目标:首先是第一个目标的所有出现,然后是第二个目标的所有出现,...... ,持续最后一个目标的所有出现。

  7. <强> II。 XSLT 2.0解决方案

    在XSLT 2.0中,可以简单地使用标准的XPath 2.0函数replace()但是,对于多次替换,解决方案仍然与上面指定的XSLT 1.0解决方案非常相似。