(xslt 1.0) 如何用 xml 中所有文本值中的一些字符串替换空格? [英] (xslt 1.0) How to replace the space with some string from all the text values in xml?

查看:21
本文介绍了(xslt 1.0) 如何用 xml 中所有文本值中的一些字符串替换空格?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

<块引用>

[从字符替换开始我最终发现了字符串在 DimitreNovatchev罗兰·鲍曼

我认为示例代码足以解释要求..

这是示例 XML:

<node1>文本节点</node1><node2>文本之间的空格</node2><节点3>必须替换为 $</node3></root>

这是我期望的输出:

<node1>text$node</node1><node2>space$between$the$text</node2><node3>$has$to$be$replaced$with$$</node3></root>

我尝试编写一个 XSLT 代码,但它没有显示所需的输出..
这是代码:

 <xsl:copy><xsl:apply-templates select="@* | node()"/></xsl:copy></xsl:模板><xsl:template match="text()[.!='']"><xsl:call-template name="rep_space"><xsl:with-param name="text" select="."/></xsl:call-template></xsl:模板><xsl:template name="rep_space"><xsl:param name="text"/><xsl:variable name="temp" select="'&#x36;'"/><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:否则><xsl:value-of select="text"/></xsl:否则></xsl:选择></xsl:模板>

<块引用>

translate(., ' ', '$') 函数有效.. 但没有达到令人满意的程度.. 我的问题是.. 如果它是一个字符串怎么办而不是性格?我的意思是,假设我打算用 ' ' 替换%20"?还有一种情况,如果输入 XML 不是漂亮的打印 XML",然后所有空间都出现在 XML 中替换为 '$' ..

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

多一个节点这是@低级

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

在下面的例子中..

<test>又一个节点</test><测试2><child>这是@下层</child></test2></新>

在所有开始标签之前都有空格字符 .. 标签之前比 节点有更多的空格 ..

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

%20%20one%20more%20node%20%20 测试2%20%20%20%20<child>this%20is%20@%20lower%20level</child>%20%20</新>

当然不是预期的..

<块引用>

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

那是很棒的学习@Dimitre,@Roland,我真的很感激并且谢谢你们..

问候,
婴幼儿.

解决方案

罗兰的意愿,这是一个尾递归解决方案:

 <xsl:param name="ptext"/><xsl:param name="ppattern"/><xsl:param name="preplacement"/><xsl:when test="not(contains($ptext, $ppattern))"><xsl:value-of select="$ptext"/></xsl:when><xsl:否则><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:否则></xsl:选择></xsl:模板>

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

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

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

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

EDIT: [it started with character replacement and I ended up with discovering string replacements with help of Dimitre Novatchev and Roland Bouman

I think the sample codes are sufficient to explain the requirements ..

This is the sample XML:

<root>
  <node1>text node</node1>
  <node2>space between the text</node2>
  <node3> has to be replaced with $</node3>
</root>

This is the Output I am expecting:

<root>
  <node1>text$node</node1>
  <node2>space$between$the$text</node2>
  <node3>$has$to$be$replaced$with$$</node3>
</root>

I have tried writing an XSLT code which isn't showing the required output ..
This is the code:

    <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>

translate(., ' ', '$')function works .. but not to the satisfactory extent .. my questions are .. what if it is a string instead of character? I mean, suppose I am intended to replace ' ' with "%20"? And one more case, What if the input XML isn't "Pretty Print XML", then all the space appearing in XML are replaced with '$' ..

Pretty print XML is the file which has proper indent, (Usually my input XMLs never have this) for example:

one more node this is @ lower level

You can observe, there are no "space characters" before <new> <test> nodes but they are actually properly indented, (With altova XMLSPY we can give a simple command in edit menu .. to make any XML files to "pretty print XML") ..

Where as in the below example ..

<new>
  <test>one more node</test>
   <test2>
    <child>this is @ lower level</child>
   </test2>
</new>

There are space chars before all the start tags .. <child> tag has more spaces before it than <test2> node ..

With the second sample xml .. all the space chars are replaced by "%20".. hence the output will be ..

<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>

certainly it is not expected ..

The solutions posted by Dimitre Novatchev and Roland Bouman can also replace a string by another string, by modifying the parameters passed to the template being called.

That was great learning @Dimitre, @Roland, I am really thankful and grateful to you guys ..

regards,
infant pro.

解决方案

As per the wish of Roland, here is a tail-recursive solution:

 <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>

Note that the recursive call is the last instruction in the template -- this is what makes it tail-recursive. The property of being tail-recursive allows a smart XSLT processor (such as Saxon or .NET XslCompiledTransform) to optimize the code, replacing the recursion with simple iteration.

Such code will not end up with a stack-overflow exception even when the "nesting" of calls is millions, whereas non-tail-recursive (and recursive) code typically raises this stack-overflow at a depth of about 1000 nested calls (this really depends on the amount of the available memory).

What if the XSLT processor is not "smart enough"? Is there another technique to avoid deep-level recursive calls stack overflow, that works with every XSLT processor?

Ask me in a separate question and I might tell you :)

这篇关于(xslt 1.0) 如何用 xml 中所有文本值中的一些字符串替换空格?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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