[英]Getting the variables in Velocity
我有一個插件項目,我正在使用Velocity模板。 用戶可以從首選項頁面更改模板正文,我想在用戶在首選項頁面中單擊“確定”時獲取模板正文中的變量。 我需要幫助從Velocity模板體中提取變量。
Velocity使用JavaCC來解析模板並創建AST。
RuntimeInstance是解析模板所需的全部內容。
RuntimeInstance ri = new RuntimeInstance();
SimpleNode node = ri.parse( reader, "templateName" );
現在您必須根據需要擴展BaseVisitor。 BaseVisitor是所有訪問者的抽象類。 BaseVisitor有一種節點類型方法,因此您可以輕松過濾AST節點。
ParserVisitor visitor = new BaseVisitor() {
@Override
public Object visit(final ASTReference node, final Object data) {
//insert here your logic ...
System.out.println(node.getFirstToken();
//use super.visit( node, data) if you need to traverse all node children
return null;
}
};
然后訪問節點...
visitor.visit(node, null);
如果您有以下模板:
some text $var other text
建議的代碼只打印$var
。
請注意,ASTReference是任何參考。 如果您有以下模板:
some text $var other text
#set( $primate = "monkey" )
這段代碼打印出來: $var
和$primate
。
我能想到的唯一方法是你向速度引擎添加這樣的東西:
VelocityContext context = new VelocityContext();
context.put("parameters", new HashMap());
...在模板中,讓用戶將值放入參數hashmap中,如下所示:
#set ($t = $parameters.put("value", "key"))
(重要的是:用戶必須為臨時參數賦值,例如$ t)
...然后,在渲染后,取出值:
HashMap map = (HashMap)context.get("parameters");
for (String key : map.keySet()) {
// ...
}
xdocreport項目完成了這項工作。
<dependency>
<groupId>fr.opensagres.xdocreport</groupId>
<artifactId>xdocreport</artifactId>
<version>1.0.6</version>
</dependency>
StringReader templateReader = new StringReader(stringyTemplateContent);
FieldsExtractor<FieldExtractor> extractor = FieldsExtractor.create();
VelocityFieldsExtractor.getInstance().extractFields(templateReader, templateName, extractor);
for (FieldExtractor fieldExtractor : extractor.getFields()) {
System.out.println(fieldExtractor.getName());
}
我以他們的VelocityFieldsExtractorTestCase
為例。
我通過注冊記憶實例的事件然后使用盒式磁帶中的事件評估模板來實現。 這不是100%防彈,因為引用可以包含很多不同的東西 ,但我還沒有看到它失敗的明顯例子。
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.event.EventCartridge;
import org.apache.velocity.app.event.ReferenceInsertionEventHandler;
import java.io.StringWriter;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
public class TemplateAnalyzer{
public static Set<String> getReferences(String template){
HashSet<String> names = new HashSet<>();
VelocityContext velocityContext = new VelocityContext();
EventCartridge ec = new EventCartridge();
ec.addEventHandler((ReferenceInsertionEventHandler)
(reference, value) -> names.add(reference)
);
ec.attachToContext(velocityContext);
Velocity.evaluate(velocityContext, new StringWriter(), "velocity", template);
return names;
}
private static Pattern namePattern = Pattern.compile("\\$!?\\{?([a-zA-Z][\\w*\\-])");
public static Set<String> getVariableNames(String template)
{
Set<String> references = getReferences(template);
return references.stream()
.map(r -> namePattern.matcher(r))
.filter(Matcher::find)
.map(m -> m.group(1))
.collect(Collectors.toSet());
}
}
你需要第二種方法來過濾掉任何不是簡單變量的東西,並清理美元符號和大括號。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.