(xslt 1.0)如何用xml中的所有文本值替换一些字符串的空格?

Inf*_*nd' 3 xml xslt xslt-1.0

编辑: [它开始于角色替换,我最终在Dimitre NovatchevRoland Bouman的帮助下发现了弦乐替换

我认为样本代码足以解释要求.

这是示例XML:

<root>
  <node1>text node</node1>
  <node2>space between the text</node2>
  <node3> has to be replaced with $</node3>
</root>
Run Code Online (Sandbox Code Playgroud)

这是我期待的输出:

<root>
  <node1>text$node</node1>
  <node2>space$between$the$text</node2>
  <node3>$has$to$be$replaced$with$$</node3>
</root>
Run Code Online (Sandbox Code Playgroud)

我试过写一个没有显示所需输出的XSLT代码..
这是代码:

    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>
  <xsl:template match="text()[.!='']">
    <xsl:call-template name="rep_space">
      <xsl:with-param name="text" select="."/>
    </xsl:call-template>
  </xsl:template>
  <xsl:template name="rep_space">
    <xsl:param name="text"/>
    <xsl:variable name="temp" select="'&#x36;'"/> 
    <xsl:choose>
      <xsl:when test="contains(text,'&#x32;')">
        <xsl:call-template name="rep_space">
          <xsl:with-param name="text" select="concat((concat(substring-before(text,' '),temp)),substring-after(text,' '))"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="text"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
Run Code Online (Sandbox Code Playgroud)

翻译(.,'','$')函数有效..但不是令人满意的程度..我的问题是..如果它是字符串而不是字符怎么办?我的意思是,假设我打算将''替换为'%20"?还有一个案例,如果输入XML不是"Pretty Print XML",那么XML中出现的所有空格都会被'$'替换.

漂亮的打印XML是具有适当缩进的文件(通常我的输入XML从来没有这个),例如:

还有一个节点,这是@ lower level

你可以观察到,在节点之前没有"空格字符",<new> <test>但它们实际上是正确缩进的(使用altova XMLSPY,我们可以在编辑菜单中给出一个简单的命令..使任何XML文件为"漂亮的打印XML").

如下例所示..

<new>
  <test>one more node</test>
   <test2>
    <child>this is @ lower level</child>
   </test2>
</new>
Run Code Online (Sandbox Code Playgroud)

在所有开始标记之前都有空格字符.. <child>标记之前的空格比<test2>节点多.

使用第二个样本xml ..所有空格字符都替换为" %20"..因此输出将是..

<new>
%20%20<test>one%20more%20node</test>
%20%20<test2>
%20%20%20%20<child>this%20is%20@%20lower%20level</child>
%20%20</test2>
</new>
Run Code Online (Sandbox Code Playgroud)

当然不是预期的..

Dimitre NovatchevRoland Bouman 发布的解决方案也可以通过修改传递给被调用模板的参数,用另一个字符串替换字符串.

那是很好的学习@Dimitre,@ Roland,我真的很感谢和感激你们..

问候,
婴儿亲.

Dim*_*hev 8

根据Roland的愿望,这是一个尾递归解决方案:

 <xsl:template name="replace">
  <xsl:param name="ptext"/>
  <xsl:param name="ppattern"/>
  <xsl:param name="preplacement"/>

  <xsl:choose>
     <xsl:when test="not(contains($ptext, $ppattern))">
      <xsl:value-of select="$ptext"/>
     </xsl:when>
     <xsl:otherwise>
       <xsl:value-of select="substring-before($ptext, $ppattern)"/>
       <xsl:value-of select="$preplacement"/>
       <xsl:call-template name="replace">
         <xsl:with-param name="ptext"
           select="substring-after($ptext, $ppattern)"/>
         <xsl:with-param name="ppattern" select="$ppattern"/>
         <xsl:with-param name="preplacement" select="$preplacement"/>
       </xsl:call-template>
     </xsl:otherwise>
  </xsl:choose>
 </xsl:template>
Run Code Online (Sandbox Code Playgroud)

请注意,递归调用是模板中的最后一条指令 - 这就是它使尾递归的原因.尾递归的属性允许智能XSLT处理器(例如Saxon或.NET XslCompiledTransform)优化代码,用简单的迭代替换递归.

即使调用的"嵌套"是数百万,这样的代码也不会以堆栈溢出异常结束,而非尾递归(和递归)代码通常会在大约1000个嵌套调用的深度引发此堆栈溢出(这真的取决于可用内存的数量).

如果XSLT处理器不够"足够聪明"怎么办?是否有另一种技术可以避免深层递归调用堆栈溢出,这适用于每个 XSLT处理器?

在一个单独的问题中问我,我可能会告诉你:)