[#recurse与XML以外的树一起使用时,我需要数据模型的Freemarker文档

问题描述 投票:0回答:1

我正在尝试在Freemarker中处理树结构,想使用#recurse,#visit指令,但是我找不到任何有关如何设置数据模型的好的文档。我可以看到的唯一示例是为XML结构创建数据模型的示例。我不需要这么详细。我的树很简单。

[尝试测试我需要的功能时,我建立了一个单元测试,但是运行时我得到了

FreeMarker template error:
For "." left-hand operand: Expected a hash, but this has evaluated to a node

这里是源代码:

public class FreemarkerXmlTests {

    static class Element implements TemplateNodeModel {
        private final String name;
        private final String text;
        private Element parent;
        private final List<Element> elements = new ArrayList<>();

        public Element(String name) {
            this(name, null);
        }

        public Element(String name, String text) {
            this.name = name;
            this.text = text;
        }

        public void add(Element element) {
            element.parent = this;
            this.elements.add(element);
        }

        public List<Element> getElements() {
            return this.elements;
        }

        public String getName() {
            return this.name;
        }

        public String getText() {
            return this.text;
        }

        public String getTitle() {
            return this.name;
        }

        public TemplateModel get(String key) {
            return null;
        }

        @Override
        public TemplateNodeModel getParentNode() throws TemplateModelException {
            return this.parent;
        }

        @Override
        public TemplateSequenceModel getChildNodes() throws TemplateModelException {
            // TODO Auto-generated method stub
            return new SimpleSequence(this.elements, cfg.getObjectWrapper());
        }

        @Override
        public String getNodeName() throws TemplateModelException {
            return this.name;
        }

        @Override
        public String getNodeType() throws TemplateModelException {
            return this.name;
        }

        @Override
        public String getNodeNamespace() throws TemplateModelException {
            return null;
        }
    }

    private static Configuration cfg;
    private static final String myTestTemplate = "<#recurse doc>\r\n" +
            "\r\n" +
            "<#macro book>\r\n" +
            "  Book element with title ${.node.title} \r\n" +
            "    <#recurse>\r\n" +
            "  End book\r\n" +
            "</#macro>\r\n" +
            "\r\n" +
            "<#macro title>\r\n" +
            "  Title element\r\n" +
            "</#macro>\r\n" +
            "\r\n" +
            "<#macro chapter>\r\n" +
            "  Chapter element with title: ${.node.title}\r\n" +
            "</#macro>";

    @BeforeClass
    public static void classInit() throws IOException {

        StringTemplateLoader stringTemplateLoader = new StringTemplateLoader();
        stringTemplateLoader.putTemplate("myTestTemplate", myTestTemplate);

        cfg = new Configuration(Configuration.VERSION_2_3_29);
        cfg.setTemplateLoader(stringTemplateLoader);
        cfg.setDefaultEncoding("UTF-8");
        cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
        cfg.setLogTemplateExceptions(false);
        cfg.setWrapUncheckedExceptions(true);
        cfg.setFallbackOnNullLoopVariable(false);
    }

    @Test
    public void basicXmlTest() throws TemplateException, IOException {

        Element doc = new Element("doc");

        Element book = new Element("book");
        book.add(new Element("title", "Test Book"));
        doc.add(book);

        Element chapter1 = new Element("chapter");
        chapter1.add(new Element("title", "Ch1"));
        chapter1.add(new Element("para", "p1.1"));
        chapter1.add(new Element("para", "p1.2"));
        chapter1.add(new Element("para", "p1.3"));
        book.add(chapter1);

        Element chapter2 = new Element("chapter");
        chapter2.add(new Element("title", "Ch2"));
        chapter2.add(new Element("para", "p2.1"));
        chapter2.add(new Element("para", "p2.2"));
        chapter2.add(new Element("para", "p2.3"));
        book.add(chapter2);

        Map<String, Object> root = new HashMap<>();
        // Put string "user" into the root
        root.put("doc", doc);

        Template temp = cfg.getTemplate("myTestTemplate");

        Writer out = new OutputStreamWriter(System.out);
        temp.process(root, out);

    }

有什么想法吗?

java freemarker
1个回答
0
投票

看看freemarker.template.TemplateNodeModel界面。您的对象必须实现该目标,或者必须(通过ObjectWrapper将其包装到实现该目标的TemplateModel中)。然后#recurse /#visit/?parent/?children/等。将与他们合作。

这是实现用于遍历JSON的TemplateNodeModel的示例:https://github.com/freemarker/fmpp/blob/master/src/main/java/fmpp/models/JSONNode.java

使用以上某些模板:https://github.com/freemarker/fmpp/tree/master/src/test/resources/tests/dl_json/src

.运算符开始,为此您需要实现TemplateHashModel(或其子接口,例如TemplateHashModelEx2)。

© www.soinside.com 2019 - 2024. All rights reserved.