惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

C
Cisco Blogs
Schneier on Security
Schneier on Security
T
Tor Project blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
T
Tenable Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
T
Threat Research - Cisco Blogs
C
CERT Recently Published Vulnerability Notes
Security Latest
Security Latest
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
NISL@THU
NISL@THU
L
Lohrmann on Cybersecurity
Scott Helme
Scott Helme
Webroot Blog
Webroot Blog
Project Zero
Project Zero
Google Online Security Blog
Google Online Security Blog
The Last Watchdog
The Last Watchdog
Spread Privacy
Spread Privacy
Hacker News: Ask HN
Hacker News: Ask HN
PCI Perspectives
PCI Perspectives
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
W
WeLiveSecurity
Attack and Defense Labs
Attack and Defense Labs
D
Darknet – Hacking Tools, Hacker News & Cyber Security
N
News | PayPal Newsroom
Help Net Security
Help Net Security
The Hacker News
The Hacker News
H
Heimdal Security Blog
O
OpenAI News
S
Security @ Cisco Blogs
N
News and Events Feed by Topic
Cyberwarzone
Cyberwarzone
Simon Willison's Weblog
Simon Willison's Weblog
G
GRAHAM CLULEY
www.infosecurity-magazine.com
www.infosecurity-magazine.com
博客园 - 叶小钗
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Hacker News - Newest:
Hacker News - Newest: "LLM"
T
Tailwind CSS Blog
大猫的无限游戏
大猫的无限游戏
A
Arctic Wolf
I
Intezer
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
S
Security Affairs
P
Proofpoint News Feed
S
Secure Thoughts
腾讯CDC
Google DeepMind News
Google DeepMind News
量子位
罗磊的独立博客

博客园 - kwklover

给同为.NET开发者普及一点Oracle数据库经验 使用mencoder转换flv为ipad/iphone下能播放的mp4格式 Lucene.net常见功能实现知识汇总 Lucene 1.9 多目录搜索的的一个bug 众里寻他千百度,蓦然回首,那人却在灯火阑珊处 问题总结:判断MS SQLSERVER临时表是否存在 小技巧:处理ASP提交的参数是经过GB2312 URL编码的 Lucene.net实现自定义排序笔记 T-SQL复习总结--用T-SQL创建,修改,管理,删除数据库 面向搜索的中文分词设计 需要整理研究的搜索引擎技术点(目录,无实际价值) 试用了一下Sqlite,总结和整理一下参考资料 数据结构与算法学习记录:快速排序 小总结:DotLucene如何才能快速生成索引? 小总结:如何表达用户是否禁止的概念 ? Web Spider提取编码方法总结 WebSpider的编码问题(乱码)浅析 VS2005 Winform程序不能启动调试,别忘了启动Terminal Services服务[记录] 系统问题解决记录:IIS 500内部错误之解决办法
模版引擎AderTemplate源代码分析笔记
kwklover · 2007-07-12 · via 博客园 - kwklover

概述

 AderTemplate是一个小型的模板引擎。无论是拿来直接使用还是用来研究模板引擎实现方式,都是一个不错的选择。本文尝试对其源代码做一些分析。

数据流程

 AderTemplate的数据处理流程可以总结为:
 
模版文件 -> 模版分析 -> Template对象 -> 分析处理TemplateElement集合 -> 输出目标文本

模版语法

 简化描述如下

 1,变量替换 :如#variable#

 2,循环语句 <ad:foreach var="x" collection="#values#" index=”i”></ad:foreach>

 3,判断语句 <ad:if test="#value#"> </ad:if>

 详细请参看AderTemplate的相关说明.

模版分析

模版分析的过程可以分成两步:
1
,把模版文件分析成Token

2,对Token流进行分析,形成Element集合

所以,首先要了解TokenElement的结构与异同。

Token的类结构:

AderTemplateToken.JPG

TokenKind(Token的类型)的详细说明:

TokenKind

说明

EOF

结束符

Comment

注释,但在AderTemplate没看到具体实现

ID

这个比较难描述,下面会通过输出Token流来直官了解下ID

TextData

文本数据,不包含模版语法的独立文本区

TagStart

Tag的开始标记,<ad:  注:Tag是一个Element,后面详述

TagEnd

Tag的结束符, > ,注意与TagClose的区别

TagEndClose

Tag的自闭结束符 ,即 />

TagClose

Tag的结束标记 </ad: <ad:对应,所以与TagEnd很容易区别

TagEquals

Tag=符号。与Tag无关的=属于TextData,TagEquals

ExpStart

AderTemplate中,语法#v#被定义为Expression.#ExpStart

ExpEnd

AderTemplate中,语法#v#被定义为Expression.#ExpEnd

LParent

左括号 (

RParent

右括号 )

Dot

即一个点 .

Comma

逗号 ,

Integer

数字

StringStart

文本的开始符,即

StringEnd

文本的结束符,即

StringText

How to description ?

为了获得更直观的认识。下面尝试把一个简单的模版文件分析的Token流输出。
模版文件,我们暂且命名为templateFile

<ad:foreach collection="#GetBookList(3)#" var="book" index="i">

<tr>

  <td>#i#</td>

  <td>#book.BookName#</td>

  <td>#book.BookCount#</td>

</tr>

</ad:foreach>

分析的代码:

static void Main(string[] args)

{

            string data = string.Empty;

            using (System.IO.StreamReader reader = new System.IO.StreamReader(templateFile))

            {

                data = reader.ReadToEnd();

            }

            //模版分析,形成Token

            TemplateLexer lexer = new TemplateLexer(data);

            Console.WriteLine("=======开始输出TemplateLexer分析出Token=======");

            do

            {

                Token token = lexer.Next();

                Console.WriteLine("\tToken类型:{0}\t行列:({1}, {2})\t数据:{3}", token.TokenKind.ToString(), token.Line, token.Col

                    , token.Data.Replace("\r\n", ""));

                if (token.TokenKind == TokenKind.EOF)

                    break;

            } while (true);

            Console.WriteLine("=======结束输出TemplateLexer分析出Token=======\r\n");

}

输出结果:

输出结果

对照表格的说明和输出结果。可以把Token理解为特定类型的文本区,即把模版文件按照TokenKind定义的类型分解成多个文本区(Token),所以分析模版文件形成的Token(集合)是一种相对线性的结构。是对模版文件的初步分析与处理。

下面继续说说Element的类体系:

AderTemplateElement.JPG

上述类关系图中可以看到Element主要有四个继承体系。

但每个类表达的意义是什么呢?

下面用一个表格做一个简单的说明。

类名

指代及其含义

Element

各种Element的基类

Text

文本类的Element , TokenKindTextDataToken相似的概念

TagClose

Tag结束符号

Tag

Tag是一个比较广的概念。上述的模版可以表示一个foreach tag

Expression

AderTemplate把语法类似#values#定义为一个Expression

FCall

Expression子类之一,表示该Expression是一个外部函数(Function)

FieldAccess

Expression子类之一,可以近似的理解成字段访问”,#book.BookName#

Name

Expression子类之一,可以近似的理解成外部变量”,#i#

StringLiteral

Expression子类之一,可以近似的理解成非数字型变量

IntLiteral

Expression子类之一,可以近似的理解成数字型变量

StringExpression

Expression子类之一,但其表示的是Expression的集合封装类

为了获得更直观的了解。我们可以通过分析上述的模版文件输出的Element来理解。因为此部分代码比较多。所以不列出了。后面会提供包含本文提到的所有代码的example.

这里需要说明的是Tag ElementTag是一个复合结构.Tag在不同的分析阶段,会些许不同。

如下面代码的(1)(2)分析出的Element是不同的。可通过输出结果来跟踪异同。

              TemplateLexer lexer = new TemplateLexer(templateData);

              TemplateParser parser = new TemplateParser(lexer);

              List<Element> elems = parser.Parse();     --(1)

              TagParser tagParser = new TagParser(elems);

              elems = tagParser.CreateHierarchy();      --(2)

TokenElement异同分析:

  在上面已经提到,Token是对模版文件的一种初步分析和分解。AderTemplate对模版文件的分析处理目标是把模版文件表达为一个Template对象。而Template对象的本质其实就是Element集合的封装类,也就是AderTemplate的对模版文件的分析其实是希望把模版文件在程序结构层面表达为一个Element的集合,从上面的ElementToken类关系图可以看出。Element远比Token复杂的多。如果直接从模版文件直接分析成Element集合结构的话,可以预见分析过程会变的相当复杂。所以AderTemplate引入了Token数据结构作为一种辅助分析手段。使得AderTemplate的对模版文件的分析过程变得更流畅和清晰了。程序的架构也变得相对优雅。所以我认为阅读AderTemplate的源代码,关键是理解TokenElement的结构和作用。特别是Element结构。因为它是AderTemplate的基础结构。即解决了在程序层面用什么结构来表达模版文件的问题。

模版分析涉及到的处理类:

TemplateLexer : 从模版文件中分析成Token流。

TemplateParser: 基于Token流分析成初步的Element集合结构。

TagParser     : 把TemplateParser分析出的Element集合做最后的优化处理。

Template(模版)对象:

 AderTemplate中。我们可以简单地认为一个Template就是经过模版分析后形成的最终的Element集合的封装体。

Template(模版)处理:

 TemplateElement集合进行分析。生成目标文本。

 此过程涉及到的技术其实不复杂,就是反射和委托,所以本文不打算详细分析此过程。否则篇幅过大。而且没什么意义。在后面我会提供一个模拟AderTemplateElement分析处理到生成目标文本过程的例字。

相关例子

 为了辅助理解AderTemplate的整个处理过程。我写了几个例子。
 1
,输出Token的结构信息。对比模版文件辅助理解Token的结构

 2,输出从Token流中分析出的Element集合的结构信息。以辅助理解Element的结构。

 3,模拟从Element集合中生成目标文本的过程。辅助理解从Element集合到生成目标文本的整个处理流程和过程。这个过程是相对简单的。从这个角度来看,AderTemplateElement集合来表达模版文件是一个比较优秀的设计。

  至于如何从模版文件分析成Element集合(Template对象)则是一个相对复杂的过程了。最好的解释还是源代码本身了。所以就不在此不做更多的分析了。

总结

AderTemplate是一个小型的模版引擎。功能并不算强大。但基本功能已经具备。从应用的角度来说,可能未必是一个最好的选择。但想学习模版引擎的开发。确是一个很不错的选择。我个人认为其架构还是比较优秀的。而且数据处理流程也很清晰。

当写作本文的时候,我阅读AderTemplate的源代码已有好些天了。依然感觉似懂非懂。到是写本文让我把思路给理清了。所以有时候。我觉得。写笔记也是一种学习。:)


AderTemplate与相关例子代码下载