FO订购清单项目标签罗马数字

时间:2018-08-06 14:13:52

标签: freemarker

我正在将两个XSLT文件转换为freemarker。一个是HTML,另一个是FO。我需要能够基于变量 typeordered 生成列表项标签,​​该变量可以是值1,a,A,i,I(用于html有序列表类型)。

原始html.xsl

<ol type="{typeordered}">
    <li>...</li>
</ol>

原始fo.xsl

<fo:list-item>
    <fo:list-item-label end-indent="label-end()">
        <fo:block><xsl:number format="{typeordered}" /></fo:block>
    </fo:list-item-label>
    ...
</fo:list-item>

FO freemarker版本。可以做小写/大写字母,但是怎么做罗马数字?似乎太复杂了?

<#macro listItemM listItem listElement n>
<fo:list-item>
    <fo:list-item-label end-indent="label-end()">
        <fo:block>
            <#if listElement.type == "ordered">
                <#if listElement.typeordered??>
                    <#if listElement.typeordered == "a">
                        ${n?lower_abc}
                    <#elseif listElement.typeordered == "A">
                        ${n?upper_abc}
                    <#else>
                        ${n}
                    </#if>
                <#else>
                    ${n}
                </#if>.
            <#else>
                &#x2022;
            </#if>
        </fo:block>
    </fo:list-item-label>
    ...
</fo:list-item>

2 个答案:

答案 0 :(得分:2)

从2.3.28开始,FreeMarker中没有内置罗马数字格式(上次我没有检查过Java)。也许应该有……但是,现在,您必须自己动手(为其写一个TemplateMethodModelEx)。

答案 1 :(得分:1)

ddekany所述,您可以创建自己的方法。这是如何执行此操作的示例:

Java代码

import freemarker.template.*;

import java.util.List;
import java.util.TreeMap;

public class RomanNumerals implements TemplateMethodModelEx {

    private final static TreeMap<Integer, String> map = new TreeMap<>();

    static {
        map.put(1000, "M");
        map.put(900, "CM");
        map.put(500, "D");
        map.put(400, "CD");
        map.put(100, "C");
        map.put(90, "XC");
        map.put(50, "L");
        map.put(40, "XL");
        map.put(10, "X");
        map.put(9, "IX");
        map.put(5, "V");
        map.put(4, "IV");
        map.put(1, "I");
    }

    // Copied from Stackoverflow https://stackoverflow.com/a/19759564/2735286
    private static String toRoman(int number) {
        int l = map.floorKey(number);
        if (number == l) {
            return map.get(number);
        }
        return map.get(l) + toRoman(number - l);
    }

    @Override
    public Object exec(List arguments) throws TemplateModelException {
        final boolean upperCase = ((TemplateBooleanModel) arguments.get(0)).getAsBoolean();
        final Integer number = ((SimpleNumber) arguments.get(1)).getAsNumber().intValue();
        String roman = toRoman(number);
        return new SimpleScalar(upperCase ? roman : roman.toLowerCase());
    }
}

在处理模板之前,您必须将其插入数据模型图中:

HashMap<String, Object> dataModel = new HashMap<>();
dataModel.put("date", new Date());
dataModel.put("roman", new RomanNumerals());
testTemplate.process(dataModel, new PrintWriter(System.out));

这是在 Freemarker 中使用它的方式:

${roman(true, 1234)}