2017-06-01 89 views
0

问题在文字 我需要插入一个字符串在其他字符串,我找到一个特殊的字符串。这些特殊字符串的定义在节点集中。最接近的通用解决方案是执行多重替换,并用插入的字符串替换匹配的特殊字符串与特殊字符串连接。我已经搜索了一个解决方案,但没有找到任何工作。XSLT 1.0:多个字符串替换的命名模板?

示例。 输入XML:

<root name ="theTop."> 
    <string>Here are some silly words</string> 
    <string>where I would like</string> 
    <other> 
     <string>to append other silly words</string> 
    </other> 
    <words> 
     <word name="word"/> 
     <word name="silly"/> 
    </words> 
</root> 

输出XML:

<root name ="theTop."> 
    <string>Here are some theTop.silly theTop.words</string> 
    <string>where I would like</string> 
    <other> 
     <string>to append other theTop.silly theTop.words</string> 
    </other> 
    <words> 
     <word name="word"/> 
     <word name="silly"/> 
    </words> 
</root> 

我还没有想出什么有用呢。这是我所想象的skelleton如何能像“素描”:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes"/> 

<xsl:variable name="append" select="/root/@name"/> 
<xsl:variable name="places" select="/root/words/word/@name"/> 

<!-- Identity rule.--> 
<xsl:template match="node()|@*"> 
    <xsl:copy> 
     <xsl:apply-templates select="node()|@*"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="//string"> 
    <xsl:call-template name="replace-multiple"> 
      <xsl:with-param name="text" select="."/> 
      <xsl:with-param name="replace" select="$places"/> 
      <xsl:with-param name="with" select="concat($append,$places)"/> 
    </xsl:call-template> 
</xsl:template> 

Obvioulsy这不起作用。它不迭代节点集$位置,我没有命名模板replace-multiple替换多个不同的字符串。

任何想法?

+0

您的输入有例如' word''while your XSLT choose such。 '/ root/words/word/@ name',这对我没有意义。然后期望的结果有'',你想转换这些元素吗?请澄清。 –

+0

啊,对不起。复制粘贴错误。现在修复。 –

回答

2

这在XSLT 1.0中的确很难做到。

问题不只是替换多个字符串。这里还有一个复杂的问题,因为替换字符串包含搜索字符串(因为您只添加了前缀)。这消除了使用单个模板遍历整个文本的可能性,并指定使用两个单独的模板:一个递归遍历多个搜索字符串,另一个遍历文本中当前搜索字符串的出现位置:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 
<xsl:strip-space elements="*"/> 

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

<xsl:template match="string"> 
    <xsl:copy> 
     <xsl:call-template name="multi-prefix"> 
      <xsl:with-param name="text" select="."/> 
     </xsl:call-template> 
    </xsl:copy> 
</xsl:template> 

<xsl:template name="multi-prefix"> 
    <xsl:param name="text"/> 
    <xsl:param name="search-strings" select="/root/words/word/@name"/> 
    <xsl:choose> 
     <xsl:when test="$search-strings"> 
      <xsl:call-template name="multi-prefix"> 
       <xsl:with-param name="text"> 
        <xsl:call-template name="single-prefix"> 
         <xsl:with-param name="text" select="$text"/> 
         <xsl:with-param name="search-string" select="$search-strings[1]"/> 
        </xsl:call-template> 
       </xsl:with-param> 
       <xsl:with-param name="search-strings" select="$search-strings[position() > 1]"/> 
      </xsl:call-template> 
     </xsl:when> 
     <xsl:otherwise> 
      <xsl:value-of select="$text"/> 
     </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 

<xsl:template name="single-prefix"> 
    <xsl:param name="text"/> 
    <xsl:param name="prefix" select="/root/@name"/> 
    <xsl:param name="search-string"/> 
    <xsl:choose> 
     <xsl:when test="contains($text, $search-string)"> 
      <xsl:value-of select="substring-before($text, $search-string)"/> 
      <xsl:value-of select="$prefix"/> 
      <xsl:value-of select="$search-string"/> 
      <xsl:call-template name="single-prefix"> 
       <xsl:with-param name="text" select="substring-after($text, $search-string)"/> 
       <xsl:with-param name="search-string" select="$search-string"/> 
      </xsl:call-template> 
     </xsl:when> 
     <xsl:otherwise> 
      <xsl:value-of select="$text"/> 
     </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 

</xsl:stylesheet> 
1

我觉得EXSLT提供str:replacehttp://exslt.org/str/functions/replace/str.replace.template.xsl)多替代,但是,我努力把它简单地用一个简单的字符串,所以我重写它的实现替换匹配的单词使用copy-ofvalue-of

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:exsl="http://exslt.org/common" 
    xmlns:str="http://exslt.org/strings" 
    exclude-result-prefixes="exsl str" 
    version="1.0"> 

    <xsl:import href="http://exslt.org/str/functions/replace/str.replace.template.xsl"/> 

    <xsl:template name="str:_replace"> 
     <xsl:param name="string" select="''"/> 
     <xsl:param name="replacements" select="/.."/> 
     <xsl:choose> 
      <xsl:when test="not($string)"/> 
      <xsl:when test="not($replacements)"> 
       <xsl:value-of select="$string"/> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:variable name="replacement" select="$replacements[1]"/> 
       <xsl:variable name="search" select="$replacement/@search"/> 
       <xsl:choose> 
        <xsl:when test="not(string($search))"> 
         <xsl:value-of select="substring($string, 1, 1)"/> 
         <xsl:value-of select="$replacement/node()"/> 
         <xsl:call-template name="str:_replace"> 
          <xsl:with-param name="string" select="substring($string, 2)"/> 
          <xsl:with-param name="replacements" select="$replacements"/> 
         </xsl:call-template> 
        </xsl:when> 
        <xsl:when test="contains($string, $search)"> 
         <xsl:call-template name="str:_replace"> 
          <xsl:with-param name="string" select="substring-before($string, $search)"/> 
          <xsl:with-param name="replacements" select="$replacements[position() > 1]"/> 
         </xsl:call-template> 
         <xsl:value-of select="$replacement/node()"/> 
         <xsl:call-template name="str:_replace"> 
          <xsl:with-param name="string" select="substring-after($string, $search)"/> 
          <xsl:with-param name="replacements" select="$replacements"/> 
         </xsl:call-template> 
        </xsl:when> 
        <xsl:otherwise> 
         <xsl:call-template name="str:_replace"> 
          <xsl:with-param name="string" select="$string"/> 
          <xsl:with-param name="replacements" select="$replacements[position() > 1]"/> 
         </xsl:call-template> 
        </xsl:otherwise> 
       </xsl:choose> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:template> 

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

    <xsl:template match="string"> 
     <xsl:param name="insert" select="ancestor::root/@name"/> 
     <xsl:param name="search" select="ancestor::root/words/word"/> 
     <xsl:param name="replace"> 
      <xsl:for-each select="$search"> 
       <replace> 
        <xsl:value-of select="concat($insert, .)"/> 
       </replace>   
      </xsl:for-each> 
     </xsl:param> 
     <xsl:copy> 
      <xsl:call-template name="str:replace"> 
       <xsl:with-param name="string" select="."/> 
       <xsl:with-param name="search" select="$search"/> 
       <xsl:with-param name="replace" select="exsl:node-set($replace)/replace"/> 
      </xsl:call-template> 
     </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet>