[英]How can I trim whitespace by Velocity
我有一个名为 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>
速度有这样的东西吗?
#trim(#render_something('xxx'))
我刚刚阅读了这篇关于Velocity Whitespace Gobbling 的文章,其中提出了一些解决方法,包括Velocity Whitespace Truncated By Line Comment 。
这基本上建议通过在每行末尾添加注释来注释换行符。 它还建议不要在宏中缩进代码以防止出现多余的(我最喜欢的词之一)空格。
TBH 这不是一个很好的解决方案,但可能适合您的需求。 只需将##
放在宏中每一行的末尾,这将使事情变得更好......有点
似乎只有 java native trim() 有效。
$someValue.trim()
对我$someValue.trim()
我挣扎了一段时间才找到解决空白吞噬的简单解决方案,所以我终于想出了一个解决方案。 它的灵感来自 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;
}
}
欢迎对我的实施提供任何反馈
受行注释截断的Velocity Whitespace 的启发,可以使用块注释代替行注释以获得更好看的结果:
#foreach( $record in $records )#**
*##if( $record.id == 0 )#**
*##end
#end
使用体面的语法突出显示注释并不是很突兀。
在创建 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 方法中是必要的,您可以在该方法中调用字符串上的实际trim()。 据我所知,Velocity 内部没有修剪,但你总是可以用这样的技巧回调 Java。
双引号是必要的,因为 #render_something 只是一个宏,而不是函数调用,这意味着宏中语句的结果被逐字放入宏“执行”点。
这是我对速度空白吞噬的替代解决方案,它允许制表模板结构。
每个模板文本在自定义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;
}
这将仅用一个注释换行符替换所有新行和调整空格。
可以使用默认上下文中的 $br 和 $sp 变量显式插入换行符和尾随空格:
private static final VelocityContext DEFAULT_CONTEXT = new VelocityContext(new HashMap<String, String>() {{
put("sp", " ");
put("br", "\n");
}});
在某些情况下,我必须像使用 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>
您可以使用标准的 java 修剪,注意您的变量是否是对象而不是字符串。
$string.trim() //work fine
$object.trim() //exception
祝你有美好的一天!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.