您的位置:首页 > 其它

freeMarker(十三)——XML处理指南之揭示XML文档

2017-01-18 13:52 183 查看
学习笔记,选自freeMarker中文文档,译自 Email: ddekany at users.sourceforge.net

前言

  尽管 FreeMarker 最初被设计用作Web页面的模板引擎, 对于2.3版本来说,它的另外一个应用领域目标是: 转换XML到任意的文本输出(比如HTML)。 因此,在很多情况下,FreeMarker 也是一个可选的XSLT。

  从技术上来说,在转换XML文档上没有什么特别之处。 它和你使用 FreeMarker 做其他事情都是一样的: 你将XML文档丢到数据模型中(和其他可能的变量), 然后你将FTL模板和数据模型合并来生成输出文本。 对于更好的XML处理的额外特性是结点FTL变量类型 (在通用的树形结构中象征一个结点,不仅仅是对XML有用)和用内建函数, 指令处理它们,你使用的XML包装器会暴露XML文档,并将作为模板的FTL变量。

  使用 FreeMarker 和XSLT有什么不同?FTL语言有常规的命令式/过程式的逻辑。 另一方面,XSLT是声明式的语言,由"很聪明"的人设计出来, 所以它并不能轻易吸收它的逻辑,也不会在很多情况下使用。而且它的语法也非常繁琐。 然而,当你处理XML文档时,XSLT的"应用模板"方法可以非常方便, 因此 FreeMarker 支持称作"访问者模式"的相似事情。 所以在很多应用程序中,写FTL的样式表要比写XSLT的样式表容易很多。 另外一个根本的不同是FTL转换结点树到文本,而XSLT转换一课树到另一棵树。 所以你不能经常在使用XSLT的地方使用 FreeMarker。

1.结点树

  我们使用如下示例的XML文档:

1 <book>
2   <title>Test Book</title>
3   <chapter>
4     <title>Ch1</title>
5     <para>p1.1</para>
6     <para>p1.2</para>
7     <para>p1.3</para>
8   </chapter>
9   <chapter>
10     <title>Ch2</title>
11     <para>p2.1</para>
12     <para>p2.2</para>
13   </chapter>
14 </book>


  W3C 的 DOM 定义XML文档模型为结点树。上面XML的结点树可以被视为:

document
|
+- element book
|
+- text "\n  "
|
+- element title
|   |
|   +- text "Test Book"
|
+- text "\n  "
|
+- element chapter
|   |
|   +- text "\n    "
|   |
|   +- element title
|   |   |
|   |   +- text "Ch1"
|   |
|   +- text "\n    "
|   |
|   +- element para
|   |   |
|   |   +- text "p1.1"
|   |
|   +- text "\n    "
|   |
|   +- element para
|   |   |
|   |   +- text "p1.2"
|   |
|   +- text "\n    "
|   |
|   +- element para
|      |
|      +- text "p1.3"
|
+- element
|
+- text "\n    "
|
+- element title
|   |
|   +- text "Ch2"
|
+- text "\n    "
|
+- element para
|   |
|   +- text "p2.1"
|
+- text "\n    "
|
+- element para
|
+- text "p2.2"


  请注意,烦扰的
"\n  "
是行的中断 (这里用
\n
指示,在FTL字符串中使用转义序列) 和标记直接的缩进空格。

  请注意和DOM相关的术语:

一棵树最上面的结点称为根 root,在XML文档中,它通常是"文档"结点, 而不是最顶层元素(本例中的
book
)。

如果B是A的 直接 后继, 我们说B结点是A结点的子结点 child。比如, 两个
chapter
元素是
book
元素的子结点, 但是
para
元素就不是。

如果A是B的 直接 前驱,也就是说, 如果B是A的子结点,我们说结点A是结点B的父结点 parent。比如,
book
元素是两个
chapter
元素的父结点, 但是它不是
para
元素的父结点。

XML文档中可以出现几种成分,比如元素,文本,注释,处理指令等。 所有这些成分都是DOM树的结点,所以就有元素结点,文本结点,注释结点等。 原则上,元素的属性也是树的结点--它们是元素的子结点--, 但是,通常我们(还有其他XML相关的技术)不包含元素的子结点。 所以基本上它们不被记为子结点。

  程序员将DOM树的文档结点放到 FreeMarker 的数据模型中, 那么模板开发人员可以以变量为出发点来使用DOM树。

  FTL中的DOM结点和 node variables 结点变量对应。这是变量类型,和字符串,数字,哈希表等类型相似。 结点变量类型使得 FreeMarker 来获取一个结点的父结点和子结点成为可能。 这是技术上需要允许模板开发人员在结点间操作,也就是,使用node 内建函数 或者
visit
recurse
指令;我们会在后续章节中展示它们的使用。

2.将XML放在数据模型中

  创建一个简单的程序来运行下面的示例是非常容易的。

1 /* Create a data-model */
2 Map root = new HashMap();
3 root.put(
4         "doc",
5         freemarker.ext.dom.NodeModel.parse(new File("the/path/of/the.xml")));


  然后你可以在基本的输出(通常是终端屏幕) 中得到一个程序可以输出XML转换的结果。

  注意:

parse
方法默认移除注释和处理指令结点。 参见API文档获取详细信息。

NodeModel
也允许你直接包装
org.w3c.dom.Node
。 首先你也许想用静态的实用方法清空DOM树,比如
NodeModel.simplify
或你自定义的清空规则。

  请注意,有可用的工具,你可以使用它们从XML文档中来生成文件, 所以你不需对通用任务来写自己的代码。

  参考程序开发指南补充知识之 和Ant一起使用FreeMarker

译自 Email: ddekany at users.sourceforge.net
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: