【问题标题】:How can I trim whitespace by Velocity如何通过速度修剪空白
【发布时间】:2020-09-02 21:51:14
【问题描述】:

我有一个叫做 render_something 的方法可以创建很多空白,例如:

<a href="#">#render_something('xxx')</a>

结果可以是:

<a href="#">     

           something that generate from redner_something


              </a> 

实际上我希望它是这样的:

<a href="#">something that generate from redner_something</a>

velocity有这样的东西吗?

#trim(#render_something('xxx'))

【问题讨论】:

    标签: java whitespace velocity removing-whitespace


    【解决方案1】:

    我刚刚在Velocity Whitespace Gobbling 上阅读了这篇文章,其中提出了一些解决方法,包括Velocity Whitespace Truncated By Line Comment

    这基本上建议通过将 cmets 放在每行的末尾来注释掉换行符。它还建议不要在宏中缩进代码以防止出现多余的(我最喜欢的词之一)空格。

    TBH 这不是一个很好的解决方案,但可能适合您的需求。只需将## 放在宏中每一行的末尾,这会让事情变得更好......有点

    【讨论】:

    • 它可以是一个替代方案。感谢您的建议。但是,我的情况无法使用您的建议,因为我无法更改 render_something。
    【解决方案2】:

    似乎只是 java native trim() 有效。

    $someValue.trim() 为我工作

    【讨论】:

    • 这对我不起作用。我确信我的变量不包含空格(正则表达式禁止),但它是在速度引擎合并后添加的。添加 trim() 不会改变任何东西。但是添加双哈希 ## 效果很好。
    【解决方案3】:

    解决方案

    在创建 VelocityEngine 的类中,添加如下方法

    public String trim(String str) {
        return str.trim()/*.replace("\n", "").replace("\r", "")*/;
    }
    

    然后将以下内容添加到您创建的 VelocityContext 中:

        context.put("trimmer", this);
    

    最后在速度模板中执行以下操作

    <a href="#">$trimmer.trim("#render_something('xxx')")</a>
    

    为什么会起作用?

    虽然 Velocity 的行为已明确定义,但有时要了解它的工作原理可能有点棘手。单独的 trim() 方法对于将字符序列从模板获取到 Java 方法中是必要的,您可以在其中调用 String 上的实际 trim()。据我所知,Velocity 内部没有修剪,但你总是可以用这样的技巧回调 Java。

    双引号是必要的,因为 #render_something 只是一个宏,而不是函数调用,这意味着宏中语句的结果被逐字放入宏被“执行”的位置。

    【讨论】:

    • 我会对此进行测试并回复您。
    【解决方案4】:

    我挣扎了一段时间才找到一个简单的解决空格吞噬的方法,所以我终于想出了一个。它的灵感来自 Vadzim 的回答和此页面 http://wiki.apache.org/velocity/StructuredGlobbingResourceLoader

    我们可以在网站上找到的 StructuredGlobbingResourceLoader 具有复杂的行为,并没有消除任何类型的空白,因此我对其进行了修改以获得简单的行为:“删除行首的任何空白,并添加每行末尾的注释”(防止换行评估)。过滤器在加载时应用于输入流。

    这种速度模板

    #if($value)
        the value is $value
    #end
    

    转化为

    #if($value)##
    the value is $value##
    #end##
    

    然后,如果您想要换行符或行首空格,则必须像 Vadzim 解释的那样在您的上下文中 put($br,"\n") 和 put($sp," ") 并明确使用它们在您的模板中。这种做法将允许您保留缩进的模板,并最大限度地控制。

    从此页面上上课http://wiki.apache.org/velocity/StructuredGlobbingResourceLoader 将扩展类更改为您需要的加载器类型(这个使用 webapp 加载器) 用我提供的代码替换 read() 方法 在您的属性中使用该类作为您的资源加载器。 webapp 加载器示例:webapp.resource.loader.class=...StructuredGlobbingResourceLoader

    public int read() throws IOException {        
        int ch;
        switch(state){
            case bol: //beginning of line, read until non-indentation character
                while(true){
                    ch = in.read();
                    if (ch!=(int)' ' && ch!=(int)'\t'){
                        state = State.content;
                        return processChar(ch);
                    }
                }
    
            case content:
                ch = in.read();
                return processChar(ch);
    
            //eol states replace all "\n" by "##\n"
            case eol1: 
                state = State.eol2;
                return (int)'#';
    
            case eol2:
                state = State.bol;
                return (int)'\n';
    
            case eof: 
                return -1;
        }
        return -1;
    }
    
    //Return the normal character if not end of file or \n
    private int processChar(int ch){
        switch(ch){
        case -1:
            state = State.eof;
            return -1;
        case (int)'\n':
            state = State.eol1;
        return (int)'#';
        default:
            return ch;
        }
    }
    

    欢迎对我的实施提出任何反馈

    【讨论】:

      【解决方案5】:

      Velocity Whitespace Truncated By Line Comment 的启发,可以使用块 cmets 代替行 cmets 以获得更好看的结果:

      #foreach( $record in $records )#**
          *##if( $record.id == 0 )#**
          *##end
      #end
      

      用一个不错的语法突出显示 cmets 不是很突兀。

      【讨论】:

        【解决方案6】:

        这是我对velocity whitespace gobbling 的替代解决方案,它允许分页模板结构。

        每个模板文本在首次加载自定义ResourceLoader时进行预处理:

        private String enhanceTemplate(String body) {
            if (!body.startsWith("##preserveWhitespace")) {
                body = body.replaceAll("(##.*)?[ \\t\\r]*\\n+[ \\t\\r]*", Matcher.quoteReplacement("##\n"));
                body = body.trim();
            }
            return body;
        }
        

        这会将所有新行和调整空格替换为一个commented newline

        可以使用默认上下文中的 $br 和 $sp 变量显式插入换行符和尾随空格:

        private static final VelocityContext DEFAULT_CONTEXT = new VelocityContext(new HashMap<String, String>() {{
            put("sp", " ");
            put("br", "\n");
        }});
        

        【讨论】:

          【解决方案7】:

          在某些情况下,我不得不像 js 或 css 一样从本质上最小化我的脚本。它运作良好,尽管人类阅读起来并不容易。消除多余空间的另一种选择:

          <ul class="tabs">#foreach($par in $bodypars)#set( $parLen = ${_MathTool.toInteger($bodypars.size())} )#set( $parLn = $parLen - 1 )#set( $thClass = 'tb'+${parLn} )#set( $thaClass = '' )#if( $foreach.index == 1 )#set( $thClass = ${thClass}+' selected' )#set( $thaClass = ' selected' )#end#if($foreach.index != 0 && $parLen <= $maxTabs)#set ( $btitle = $_XPathTool.selectSingleNode($par,'item-subtitle') )<li class="${thClass}">#if($!btitle && $btitle != '')<a href="#" class="#cleanString($btitle.value.toLowerCase())${thaClass}">$_SerializerTool.serialize($btitle, true)</a>#end</li>#end#end</ul>
          

          【讨论】:

            【解决方案8】:

            你可以使用标准的 java trim,注意你的变量是否是一个对象而不是字符串。

            $string.trim()  //work fine
            $object.trim()  //exception
            

            祝你有美好的一天!

            【讨论】:

              猜你喜欢
              • 2010-11-14
              • 1970-01-01
              • 2018-08-26
              • 2017-03-16
              • 1970-01-01
              • 2012-08-07
              • 2013-10-21
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多