字符串内置函数

目录

boolean

字符串转为布尔值。字符串必须是 true 或 false (大小写敏感),或者必须是由 boolean_format 设置的特定格式。

<#-- boolean 字符串转为布尔值 -->
<#assign booleanVal="true">
<#if (booleanVal?boolean)> True <#else> False </#if>

如果字符串不是适当的格式,将抛出如下错误信息:

Exception in thread "main" FreeMarker template error:
Can't convert this string to boolean: "True"
The blamed expression:
==> booleanVal?boolean  [in template "template18.ftl" at line 9, column 7]

cap_first

字符串中的首单词的首字母大写。例如:

${"  green mouse"?cap_first}
${"GreEN mouse"?cap_first}
${"- green mouse"?cap_first}

输出结果:

  Green mouse
GreEN mouse
- green mouse

在 “- green mouse” 中,第一个单词是 “-”。

capitalize

字符串中所有单词的首字母大写。例如:

${"  green  mouse"?capitalize}
${"GreEN mouse"?capitalize}

输出结果:

  Green Mouse
Green Mouse

chop_linebreak

如果一个字符串的末尾有换行,将换行打断;否则不改变字符串。例如:

<#assign str1="Java template engine;\n">
<#assign str2="generates HTML web pages, e-mails, configuration files, source code, etc.">
A|${str1} ${str2}|
B|${str1?chop_linebreak} ${str2}|

输出结果:

A|Java template engine;
 generates HTML web pages, e-mails, configuration files, source code, etc.|
B|Java template engine; generates HTML web pages, e-mails, configuration files, source code, etc.|

注意:在B开头的行忽略了 str1 末尾的换行符;

contains

从 FreeMarker 2.3.1 版本开始可用,在 2.3 版本中是没有的。

如果源字符串包含 contains 函数指定的子串,那么返回 true;否则,返回false。比如:

<#if "piceous"?contains("ice")>It contains "ice"</#if>

输出结果:

It contains "ice"

date, time, datetime

将字符串转换成日期值,时间或日期-时间值。需要一个由 date_format,time_format 和 datetime_format 设置指定的格式。如果字符串不是适当的格式,那么当访问该内建函数时,就会发生错误中止模板的处理。

<#-- The date_format, time_format and datetime_format settings must match this format! -->
<#assign someDate = "Oct 25, 1995"?date>
<#assign someTime = "3:05:30 PM"?time>
<#assign someDatetime = "Oct 25, 1995 03:05:00 PM"?datetime>

<#-- Changing the setting value changes the expected format: -->
<#setting datetime_format="iso">
<#assign someDatetime = "1995-10-25T15:05"?datetime>

也可以指定明确的格式,比如 ?datetime.format 或 ?datetime["format"] (由于历史原因,也可以是 ?datetime("format")),它们与 ?date 和 ?time 是相同的。 对于格式化值的语法和意义,可以参考 date_format, time_format 和 datetime_format 设置的可能的值。 比如:

<#-- Parsing XML Schema xs:date, xs:time and xs:dateTime values: -->
<#assign someDate = "1995-10-25"?date.xs>
<#assign someTime = "15:05:30"?time.xs>
<#assign someDatetime = "1995-10-25T15:05:00"?datetime.xs>

<#-- Parsing ISO 8601 (both extended and basic formats): -->
<#assign someDatetime = "1995-10-25T15:05"?datetime.iso>
<#assign someDatetime = "19951025T1505"?datetime.iso>

<#-- Parsing with SimpleDateFormat patterns: -->
<#assign someDate = "10/25/1995"?date("MM/dd/yyyy")>
<#assign someTime = "15:05:30"?time("HH:mm:ss")>
<#assign someDatetime = "1995-10-25 03:05 PM"?datetime("yyyy-MM-dd hh:mm a")>

避免误解,左侧值无需是字符串文本。比如,当从 XML 结点 (此处的所有值都是未被解析的字符串) 读取数据,那么就需要这样来做 order.confirmDate?date.xs,将字符串转化成真实的日期。当然,格式也可以是一个变量,比如:"..."?datetime[myFormat]。

ends_with

返回是否这个字符串以参数中指定的子串结尾。 比如:

<#if "ahead"?ends_with("head")>
    字符串以head结尾
<#else>
    不是以head结尾
</#if>
<#if "head"?ends_with("head")>
    字符串以head结尾
<#else>
    不是以head结尾
</#if>

输出结果:

    字符串以head结尾
    字符串以head结尾

ensure_ends_with

从 FreeMarker 2.3.21 版本开始可用

如果字符串没有以第一个参数指定的子串结尾,那么就会将它加到字符串后面,否则返回原字符串。比如:

${"foo"?ensure_ends_with("/")}
${"foo/"?ensure_ends_with("/")}

输出结果:

foo/
foo/

ensure_starts_with

从 FreeMarker 2.3.21 版本开始可用

如果字符串没有以第一个参数指定的子串开头, 那么就会将它加到字符串开头,否则返回原字符串。比如:

${ "foo"?ensure_starts_with("/") }
${ "/foo"?ensure_starts_with("/") }

输出结果:

/foo
/foo

如果指定两个参数,那么第一个参数就被解释成Java正则表达式,如果它不匹配字符串的开头,那么第二个参数指定的字符串就会添加到字符串开头。 比如:

${ someURL?ensure_starts_with("[a-zA-Z]+://", "https://") }

会检查如果字符串是否以 "[a-zA-Z]+://" 开头 (请注意,不需要 ^),如果不是的话,就添加 "https://"。

该方法也接受第三个标志位参数。因为调用两个参数暗指 "r" (也就是正则表达式模式),那么就需要第三个参数了。

值得注意的一点是当不需要第一参数被解释成正则表达式,而只是普通文本, 但是又想让比较是大小写敏感的,那么此时就需要使用 "i" 作为第三个参数。比如:

${ "HTTP://www.hxstrive.com"?ensure_starts_with("https://", "https://www", "i") }
${ "www.hxstrive.com"?ensure_starts_with("https://", "https://", "i") }

如果字符串不是以“https://”开头(忽略大小写),则追加“https://”。

groups

这个函数只作用于内建函数 matches 的结果,见 matches 内置函数

html

字符串按照HTML标记输出。也就是说,下面字符串将会被替代:

  • < 替换为 &lt;

  • > 替换为 &gt;

  • & 替换为 &amp;

  • " 替换为 &quot;

如果程序员将 FreeMarker 的 incompatible_improvements 设置为 2.3.20 或更高;那么“'”被替换为“&#39;”,例如:

<#assign htmlVal="<label>Username: Administrator</label>">
<#assign htmlAttr="<i>color:red;</i>">
<p attr="${htmlAttr?html}">${htmlVal?html}</p>

输出结果:

<p attr="&lt;i&gt;color:red;&lt;/i&gt;">&lt;label&gt;Username: Administrator&lt;/label&gt;</p>

注意:如果想安全地插入一个属性,必须在 HTML 模板中使用 引号标记 (是 ",而不是 ') 为属性值加引号:

<input type=text name=user value="${user?html}">

注意:在 HTML 页面中,通常想对所有插值使用这个内建函数。 所以可以使用 escape 指令来节约输入,减少偶然错误的机会。

index_of

返回第一次字符串中出现子串时的索引位置。例如:

${"abcabc"?index_of("bc")}

输出结果:

1

而且,你可以指定开始搜索的索引位置:

${"abcabc"?index_of("bc", 2) }

输出结果:

4

第二个参数的数值没有限制:如果它是负数,那就和 0 是相同效果了,如果它比字符串的长度还大,那么就和它是字符串长度那个数值是一个效果。 小数会被切成整数。

如果第一个参数作为子串没有在该字符串中出现时 (如果你使用了第二个参数,那么就从给定的序列开始),那么就返回 -1。

j_string

根据 Java 语言字符串转义规则来转义字符串,所以它很安全的将值插入到字符串类型中。要注意它不会在被插入的值的两侧添加引号;你需要在字符串值内部来使用。

所有 UCS 编码下指向 0x20 的字符会被转义。当它们在 Java 语言中 (比如\n,\t等) 没有专门的转义序列时,将会被用 UNICODE 进行转义替换 (\uXXXX)。

例如:

<#assign beanName = 'The "foo" bean.'>
String BEAN_NAME = "${beanName?j_string}";

输出结果:

String BEAN_NAME = "The \"foo\" bean.";

js_string

根据 JavaScript 语言字符串转义规则来转义字符串, 所以它很安全的将值插入到字符串类型中。要注意,它不会在被插入的值两侧添加引号;你需要在字符串值内部来使用。

引号 (") 和单引号 (') 要被转义。 从 FreeMarker 2.3.1 开始,也要将 > 转义为 \>(为了避免 </script>)。

所有在 UCS 编码下指向 0x20 的字符将会被转义。当它们在 JavaScript 中没有专用的转义序列时 (比如 \n,\t 等),它们会被 UNICODE 字符代替 (\uXXXX)。

例如:

<#assign user = "Big Joe's \"right hand\"">
<script>
  alert("Welcome ${user?js_string}!");
</script>

输出结果:

<script>
  alert("Welcome Big Joe\'s \"right hand\"!");
</script>

json_string

根据 JSON 语言的字符串规则来转义字符串,所以在字符串中插入值是安全的。要注意它不会在被插入的值两侧添加引号;你需要在字符串值内部来使用。

这不会转义 ' 字符,因为 JSON 字符串必须使用 " 来括起来。它会在 < 之后直接出现的 /(斜杠) 字符转义为 \/,来避免 </script> 等。它也会在 ]] 之后转义 > 字符为 \u003E,来避免退出 XML 的 CDATA 段。

所有在 UCS 编码下指向 0x20 的字符会被转义。当在 JSON 中没有专用的转义序列时 (比如 \n,\t 等), 它们会被 UNICODE 字符代替 (\uXXXX)。

例如:

<#assign jsonStr="Administrator,</'admin']]>">
{"name":"${jsonStr?json_string}", "age":28}

输出结果:

{"name":"Administrator,<\/'admin']]\u003E", "age":28}

keep_after

从 FreeMarker 2.3.21 版本开始可用。

移除字符串中的一部分内容,该部分是给定子串第一次出现之前的部分。如果参数字符串没有找到,它会返回空串。如果参数是长度为0的字符串,它会返回源字符串,不会改变。比如:

正常:${"abcdefgh"?keep_after("de")}
没有找到:${"abcdefgh"?keep_after("hah")}
空参数:${"abcdefgh"?keep_after("")}

输出结果:

正常:fgh
没有找到:
空参数:abcdefgh

该方法接受可选的标志位参数,作为它的第二个参数(r 表示启用正则表达式,\s 表示空格,而 \s* 表示一个或多个空格):

${"foo : bar"?keep_after(r"\s*:\s*", "r")}

输出结果:

bar

keep_after_last

该内建函数从 FreeMarker 2.3.22 版本开始可用。

和 keep_after 相同,但是它会保留参数最后一次出现后的部分,而不是第一次。比如:

${"foo.bar.txt"?keep_after_last(".")}

输出结果:

txt

若使用 keep_after 则会得到 bar.txt,keep_after会保留第一次和参数匹配的部分。

keep_before

从 FreeMarker 2.3.21 版本开始可用。

移除字符串的一部分,该部分是从给定子串开始的部分。 如果参数字符串没有找到,它会返回源字符串,不会改变。 如果参数是长度为0的字符串,它会返回空串。比如:

正常:${"abcdef"?keep_before("de")}
没有找到:${"abcdef"?keep_before("hah")}
空参数:${"abcdef"?keep_before("")}

输出结果:

正常:abc
没有找到:abcdef
空参数:

该方法接受可选的标志位参数,作为它的第二个参数(r 表示启用正则表达式,\s 表示空格,而 \s* 表示一个或多个空格):

${"foo : bar"?keep_before(r"\s*:\s*", "r")}

输出结果:

foo

keep_before_last

从 FreeMarker 2.3.22 版本开始可用。

和 keep_before 相同,但是保留参数最后一次出现之前的部分,而不是第一次出现之前。比如:

${"foo.bar.txt"?keep_after_last(".")}

输出结果:

foo.bar

若使用 keep_before 则会得到 foo。

last_index_of

返回最后一次 (最右边) 字符串中出现子串时的索引位置。它返回子串第一个(最左边) 字符所在位置的索引。如果第一个参数作为子串没有在该字符串中出现时 (如果你使用了第二个参数,那么就从给定的序列开始),那么就返回-1。例如:

${"abcabc"?last_index_of("ab")}

输出结果:

3

 而且可以使用第二个参数指定开始搜索的索引。例如:

${ "abcabc"?last_index_of("ab", 2) }

输出结果:

0

注意:第二个参数暗示了子串开始的最大索引。对第二个参数的数值没有限制: 如果它是负数,那么效果和 ?last_index_of("ab", 0) 是一样的;如果它比字符串的长度还大,那么就和它是字符串长度那个数值是一个效果。小数会被切成整数。

left_pad

从 FreeMarker 2.3.1 版本开始可用。

如果它仅仅用1个参数,那么它将在字符串的开始插入空白,直到整个串的长度达到参数指定的值。如果字符串的长度达到指定数值或者比指定的长度还长,那么就什么都不做了。比如这样:

[${""?left_pad(5)}]
[${"a"?left_pad(5)}]
[${"ab"?left_pad(5)}]
[${"abc"?left_pad(5)}]
[${"abcd"?left_pad(5)}]
[${"abcde"?left_pad(5)}]
[${"abcdef"?left_pad(5)}]
[${"abcdefg"?left_pad(5)}]
[${"abcdefgh"?left_pad(5)}]

输出结果:

[     ]
[    a]
[   ab]
[  abc]
[ abcd]
[abcde]
[abcdef]
[abcdefg]
[abcdefgh]

如果使用了两个参数,那么第一个参数表示的含义和你使用一个参数时的相同, 第二个参数指定用什么东西来代替空白字符。比如:

[${""?left_pad(5, "-")}]
[${"a"?left_pad(5, "-")}]
[${"ab"?left_pad(5, "-")}]
[${"abc"?left_pad(5, "-")}]
[${"abcd"?left_pad(5, "-")}]
[${"abcde"?left_pad(5, "-")}]

输出结果:

[-----]
[----a]
[---ab]
[--abc]
[-abcd]
[abcde]

第二个参数也可以是个长度比1大的字符串。那么这个字符串会周期性的插入,比如:

[${""?left_pad(8, ".oO")}]
[${"a"?left_pad(8, ".oO")}]
[${"ab"?left_pad(8, ".oO")}]
[${"abc"?left_pad(8, ".oO")}]
[${"abcd"?left_pad(8, ".oO")}]

输出结果:

[.oO.oO.o]
[.oO.oO.a]
[.oO.oOab]
[.oO.oabc]
[.oO.abcd]

第二个参数必须是个字符串值,而且至少有一个字符。

length

字符串中字符的数量。例如:length=${"administrator"?length},将输出 length=13。

lower_case

字符串的小写形式。比如 "GrEeN MoUsE"?lower_case 将会是 "green mouse"。

matches

该内建函数将字符串和给定的正则表达式进行精确匹配。而且,它会返回匹配子串的列表。返回值是多类型值:

  • 布尔值:如果字符串整体匹配了模式,就是 true, 否则就是 false。比如:"fooo"?matches('fo*') 就是 true,但是 "fooo bar"?matches('fo*') 是 false。

  • 序列:字符串匹配的子串的列表。很有可能是长度为 0 的序列。

比如:

<#if "fxo"?matches("f.?o")>Matches.<#else>Does not match.</#if>
<#assign res = "foo bar fyo"?matches("f.?o")>
<#if res>Matches.<#else>Does not match.</#if>

Matching sub-strings:
<#list res as m>
- ${m}
</#list>

输出结果:

Matches.
Does not match.

Matching sub-strings:
- foo
- fyo

如果正则表达式包含分组 (圆括号),那么可以使用 groups 内建函数来访问它们:

<#-- Entire input match -->
<#assign res = "John Doe"?matches(r"(\w+) (\w+)")>
<#if res> <#-- Must not try to access groups if there was no match! -->
  First name: ${res?groups[1]}
  Second name: ${res?groups[2]}
</#if>

<#-- Subtring matches -->
<#assign res = "aa/rx; ab/r;"?matches("(.+?)/*(.+?);")>
<#list res as m>
  - "${m}" is "${m?groups[1]}" per "${m?groups[2]}"
</#list>

输出结果:

  First name: John
  Second name: Doe
  
  - "aa/rx;" is "a" per "a/rx"
  - " ab/r;" is " " per "ab/r"

请注意,上面的 groups 对子串匹配和整个字符串匹配的结果都起作用。matches 接受可选的第二参数,标志位。请注意,它不支持标志 f,也会忽略 r 标志。

number

字符串转化为数字格式。这个数字必须是 "计算机语言" 格式。也就是说, 它必须是本地化独立的形式,小数的分隔符就是一个点,没有分组。

该内建函数识别FreeMarker模板语言使用的数字格式。此外, 它也识别科学记数法(比如 "1.23E6","1.5e-8") 从 FreeMarker 2.3.21 版本开始,它也识别所有XML Schema数字格式,比如 NaN,INF,-INF, 还有Java本地格式Infinity 和 -Infinity。

如果字符串不是适当的格式,当尝试访问该内建函数时就会发生错误, 并中止模板执行。

实际上,字符串是由当前 arithmetic_engine 的 toNumber 方法解析的,这是可以配置的设置项。不过该方法应该和上面描述的行为相似。

replace

在源字符串中,用另外一个字符串来替换原字符串中出现它的部分。 它不处理词的边界。比如:

${"this is a car acarus"?replace("car", "bulldozer")}

输出结果:

this is a bulldozer abulldozerus

替换是从左向右执行的。这就意味着:

${"aaaaa"?replace("aaa", "X")}

输出结果:

Xaa

如果第一个参数是空字符串,那么所有的空字符串将会被替换,比如 "foo"?replace("", "|"),就会得到 "|f|o|o|"。replace 接受可选的标志位参数,作为它的第三参数。

right_pad

从 FreeMarker 2.3.1 版本开始可用,在2.3版本中是没有的。

它和 left_pad 相同, 但是它从末尾开始插入字符而不是从开头。比如:

[${""?right_pad(5)}]
[${"a"?right_pad(5)}]
[${"ab"?right_pad(5)}]
[${"abc"?right_pad(5)}]
[${"abcd"?right_pad(5)}]
[${"abcde"?right_pad(5)}]
[${"abcdef"?right_pad(5)}]
[${"abcdefg"?right_pad(5)}]
[${"abcdefgh"?right_pad(5)}]

[${""?right_pad(8, ".oO")}]
[${"a"?right_pad(8, ".oO")}]
[${"ab"?right_pad(8, ".oO")}]
[${"abc"?right_pad(8, ".oO")}]
[${"abcd"?right_pad(8, ".oO")}]

输出结果:

[     ]
[a    ]
[ab   ]
[abc  ]
[abcd ]
[abcde]
[abcdef]
[abcdefg]
[abcdefgh]

[.oO.oO.o]
[aoO.oO.o]
[abO.oO.o]
[abc.oO.o]
[abcdoO.o]

remove_beginning

从 FreeMarker 2.3.21 版本开始可用。

从字符串的开头移除参数中的子串,如果它不以参数中的子串开头, 那么就或者返回原字符串。比如:

${"abcdef"?remove_beginning("abc")}
${"foobar"?remove_beginning("abc")}

输出结果:

def
foobar

remove_ending

从 FreeMarker 2.3.21 版本开始可用。

从字符串的结尾移除参数中的子串,如果它不以参数中的子串结尾, 那么就或者返回原字符串。比如:

${"abcdef"?remove_ending("def")}
${"foobar"?remove_ending("def")}

输出结果:

abc
foobar

rtf

字符串作为富文本(RTF 文本),也就是说,下列字符串:

\ 替换为 \\
{ 替换为 \{
} 替换为 \}

split

它被用来根据指定的字符串参数分割原字符串,且返回分割后的字符串序列。 比如:

<#list "someMOOtestMOOtext"?split("MOO") as x>
- ${x}
</#list>

输出结果:

- some
- test
- text

请注意,假设所有的分隔符都在新项之前出现 (除了使用 "r" 标志 - 后面详细介绍) 因此:

<#list "some,,test,text,"?split(",") as x>
- "${x}"
</#list>

输出结果:

- "some"
- ""
- "test"
- "text"
- ""

split 接受可选的标志位参数,作为它的第二个参数。由于历史使用 r (正则表达式) 标志的差错;它会从结果列表中移除空元素, 所以在最后示例中使用 ?split(",", "r"),"" 会从输出中消失。要检查一个字符串是否以...结尾或者要附加它, 使用 ensure_ends_with 内建函数。

starts_with

如果字符串以指定的子字符串开头,那么返回true。 比如 "redirect"?starts_with("red") 返回布尔值 true,而且 "red"?starts_with("red") 也返回 true。要检查一个字符串是否以...开头或者要在前面附加它, 使用 ensure_starts_with 内建函数。

string (当被用作是字符串值时)

什么也不做,仅仅返回和其内容一致的字符串。例外的是, 如果值是一个多类型的值(比如同时有字符串和序列两种), 那么结果就只是一个简单的字符串,而不是多类型的值。 这可以被用来防止人为多输入。

substring (已废弃)

从 FreeMarker 2.3.21 版本开始,该内建函数被废弃,由字符串切分替代,比如:str[from..<toExclusive],str[from..] 和 str[from..*maxLength]。

如果处理 XML 那么有一点警示:因为分割表达式作用于序列和字符串,而且 XML 结点通常既是序列又是字符串,那么相等的表达式是 someXmlNode?string[from..<toExclusive] 和 exp?string[from..],因为没有 ?string 它会分割结点序列而不是结点的字符串值。

注意:一些典型的字符串分割的用例已经由一些内建函数方便地实现:remove_beginning,remove_ending,keep_before,keep_after,keep_before_last,keep_after_last

概要: exp?substring(from, toExclusive),也可以使用 exp?substring(from) 调用。

字符串的子串 from 是第一个字符的索引。它必须是数字,最小是0并且小于或等于 toExclusive,否则就会发生错误并且中止模板处理。toExclusive 是子串最后一个字符之后的字符位置索引,换句话说,它比最后一个字符的索引大1。它必须是一个数字,最小是0并且小于或等于字符串的长度,否则就会发生错误并且中止模板处理。如果 toExclusive 被忽略了,那么默认就是字符串的长度。如果参数是数字但不是整数,那么只有数字中的整数部分会被使用。例如:

- ${'abc'?substring(0)}
- ${'abc'?substring(1)}
- ${'abc'?substring(2)}
- ${'abc'?substring(3)}

- ${'abc'?substring(0, 0)}
- ${'abc'?substring(0, 1)}
- ${'abc'?substring(0, 2)}
- ${'abc'?substring(0, 3)}

- ${'abc'?substring(0, 1)}
- ${'abc'?substring(1, 2)}
- ${'abc'?substring(2, 3)}

输出结果:

- abc
- bc
- c
-

-
- a
- ab
- abc

- a
- b
- c

trim

去掉字符串首尾的空格。例如:

(${"  green mouse  "?trim})

输出结果:

(green mouse)

uncap_first

和 cap_first 相反。 字符串中所有单词的首字母小写。例如:

${"Hello World"?uncap_first}

输出结果:

hello World

upper_case

字符串的大写形式。比如:"GrEeN MoUsE" 将会是 "GREEN MOUSE"。

${"GrEeN MoUsE"?upper_case}

url

从 FreeMarker 2.3.1 版本开始可用。 在2.3版本中是没有的。

在 URL 之后的字符串进行转义。这意味着,所有非 US-ASCII 的字符和保留的 URL 字符将会被 %XX 形式转义。例如:

<#assign x = 'a/b c'>
${x?url}

输出结果 (假设用来转义的字符集是US-ASCII兼容的字符集):

a%2Fb%20c

请注意,它会转义所有保留的 URL 字符 (/,=,&,等...),所以编码可以被用来对查询参数的值进行,比如:

<a href="foo.cgi?x=${x?url}&y=${y?url}">Click here...</a>

为了进行URL转义,必须要选择字符集,它被用来计算被转义的部分 (%XX)。 如果你是HTML页面设计者,而且你不懂这个,不要担心: 程序员应该配置 FreeMarker,则它默认使用恰当的字符集。如果你是一个比较热衷于技术的人,那么你也许想知道被 url_escaping_charset 设置的指定字符集,它可以在模板的执行时间设置。例如:

<#--
  This will use the charset specified by the programmers
  before the template execution has started.
-->
<a href="foo.cgi?x=${x?url}">foo</a>

<#-- Use UTF-8 charset for URL escaping from now: -->
<#setting url_escaping_charset="UTF-8">
<#-- This will surely use UTF-8 charset -->
<a href="bar.cgi?x=${x?url}">bar</a>

此外,你可以明确地指定一个为单独 URL 转义的字符集,作为内建函数的参数:

<a href="foo.cgi?x=${x?url('ISO-8895-2')}">foo</a>

如果内建函数 url 没有参数,那么它会使用由 url_escaping_charset 设置的字符集。url_escaping_charset 通过 java 代码或框架进行设置,它默认不会被设置。 

如果 url_escaping_charset 没有被设置,那么 FreeMarker 会使用 output_encoding 的设置,output_encoding 也是通过 java 代码或框架进行设置,会被默认设置。 

如果 output_encoding 也没有被设置,那么没有参数的内建函数 url 将不会被执行, 而且它会引起运行时错误。

当然,有参数的 url 函数将会执行。

可以使用 setting 指令在模板中设置 url_escaping_charset(不推荐),output_encoding 不能由 setting 指令来设置。

url_path

从 FreeMarker 2.3.21 版本开始可用。

它和 url 内建函数相同,只是它不转义斜杠 (/)字符。这就是意味着用来转义使用了斜杠 (不是反斜杠) 的路径 (比如操作系统或一些内容仓库的路径),转义之后它们可以插入到URL中。 需要该转义的常用原因是文件夹名称或文件名称可能含有非US-ASCII字母 ("国家" 标准符号)。例如:

${"https://localhost:8090/test/index.html"?url_path("UTF-8")}
${"D:\\learn\\open_source\\freemarker_learn\\pom.xml"?url_path("UTF-8")}

输出结果:

http%3A//localhost%3A8090/test/index.html
D%3A%5Clearn%5Copen_source%5Cfreemarker_learn%5Cpom.xml

注意:和 url 内建函数相似,希望的 URL 转义字符 (或者后退,输出编码) 必须要在 FreeMarker的配置设置项中设置,否则内建函数就会报错。或者可以指定字符集,比如:somePath?url_path('utf-8')。

word_list

将字符串使用空格分隔,返回分隔后的字符串单词序列,单词的顺序为单词出现在字符串中的顺序。例如:

<#assign words = "   a bcd, .   1-2-3"?word_list>
<#list words as word>[${word}]</#list>

输出结果:

[a][bcd,][.][1-2-3]

xhtml

字符串作为XHTML格式文本,下面这些:

< 替换为 &lt;
> 替换为 &gt;
& 替换为 &amp;
" 替换为 &quot;
' 替换为 &#39;

该内建函数和 xml 内建函数的唯一不同是 xhtml内建函数转义“'”为 &#39;,而不是 &apos;, 因为一些老版本的浏览器不能正确解释 &apos;。例如:

${"<?xml version=\"1.0\" encoding='UTF-8'?><note><to>George</to></note>"?xhtml}

输出结果:

&lt;?xml version=&quot;1.0&quot; encoding=&#39;UTF-8&#39;?&gt;&lt;note&gt;&lt;to&gt;George&lt;/to&gt;&lt;/note&gt;

注意:上面将单引号“'”转换成了 &#39,而不是 &apos。

xml

字符串作为XML格式文本,下面这些:

< 替换为 &lt;
> 替换为 &gt;
& 替换为 &amp;
" 替换为 &quot;
' 替换为 &apos;

例如:使用内置函数 xml 转换 XML 字符串

${"<?xml version=\"1.0\" encoding='UTF-8'?><note><to>George</to></note>"?xml}

输出结果:

&lt;?xml version=&quot;1.0&quot; encoding=&apos;UTF-8&apos;?&gt;&lt;note&gt;&lt;to&gt;George&lt;/to&gt;&lt;/note&gt;


说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
公众号