1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
//! 命名空间前缀映射 —— 对应 Java `Template` 的 ns_prefixes(`<#ftl ns_prefixes=...>`)。
use std::collections::HashMap;
/// 命名空间前缀映射 —— 对应 Java `Template` 的 ns_prefixes(`<#ftl ns_prefixes=...>`)。
/// 特殊前缀:"D"(`Template.DEFAULT_NAMESPACE_PREFIX`)注册为默认命名空间;
/// "N"(`Template.NO_NS_PREFIX`)保留、不可注册。
#[derive(Debug, Default)]
pub struct NsPrefixes {
/// prefix → URI(不含 "D"——它进入 default_ns)
prefix_to_uri: HashMap<String, String>,
/// URI → prefix(getPrefixForNamespace 反查)
uri_to_prefix: HashMap<String, String>,
/// 默认命名空间(`D` 前缀)
default_ns: Option<String>,
}
impl NsPrefixes {
pub fn new(map: HashMap<String, String>) -> Self {
let mut p = NsPrefixes {
prefix_to_uri: HashMap::new(),
uri_to_prefix: HashMap::new(),
default_ns: None,
};
for (prefix, uri) in map {
// Java Template.addNsPrefix(Template.java:920-951):"N" 保留非法;
// "D" 注册为 defaultNS;其余入 prefixToNamespaceURILookup + 反查表
// (同 URI 只能映射一个前缀,重复即非法——解析期已校验)
if prefix == "N" {
continue;
}
if prefix == "D" {
p.default_ns = Some(uri);
} else {
p.uri_to_prefix.insert(uri.clone(), prefix.clone());
p.prefix_to_uri.insert(prefix, uri);
}
}
p
}
/// 默认命名空间 URI(Java Template.getDefaultNS)
pub fn get_default_ns(&self) -> Option<&str> {
self.default_ns.as_deref()
}
/// prefix → URI(Java Template.getNamespaceForPrefix:"" → defaultNS 或 "")
pub fn get_namespace_for_prefix(&self, prefix: &str) -> Option<&str> {
if prefix.is_empty() {
return Some(self.default_ns.as_deref().unwrap_or(""));
}
self.prefix_to_uri.get(prefix).map(|s| s.as_str())
}
/// URI → prefix(Java Template.getPrefixForNamespace:null → null;
/// "" → defaultNS 为 null ? "" : "N";== defaultNS → "";否则反查表)
pub fn get_prefix_for_namespace(&self, ns_uri: &str) -> Option<&str> {
if ns_uri.is_empty() {
return Some(if self.default_ns.is_none() { "" } else { "N" });
}
if self.default_ns.as_deref() == Some(ns_uri) {
return Some("");
}
self.uri_to_prefix.get(ns_uri).map(|s| s.as_str())
}
}