一个简单的 HTML 标记解析器






3.90/5 (12投票s)
一个非常简单的 HTML 模板解析器,它用有意义的文本替换用户定义的标记。
引言
在开发我的最新网站时,我研究了许多 CMS 系统,并测试了在 Visual Studio 中生成动态 Web 内容的不同方法。似乎没有一个适合。我想要的是一种非常简单的方式来显示动态内容 - 一种简单的 API。我希望能够编辑基本的 HTML 文件来做到这一点。在研究了创建我自己的 HTTPhandler 的方法并决定这对我的应用程序来说是多余的之后,我回想起 Delphi 已经实现了一个优雅的解决方案:PageProducers。
自从最近转投 C#.NET 阵营以来,我决定重新创建一个简单的 Delphi 的 PageProducer
类的版本。我提出的 HTML 模板解析器提供了一种简单的方法来实现用户定义的 HTML 模板。它允许您定义自己的标记,并在运行时在代码中用您希望的值替换这些标记。它不是您见过的最复杂的解析器,但它以最少的麻烦完成了工作。
概述
调用代码实例化一个 TokenParser
类的对象,并为其分配一个事件处理程序。
parser = new TokenParser(fileName); // fileName is the path and name of the HTML file.
parser.OnToken += this.OnToken;
public void OnToken(string strToken, ref string strReplacement)
{
if (strToken == "TESTME")
strReplacement = "Moose Butts a-Flyin!";
else
strReplacement = "Huh?";
}
完成此操作后,只需从 TokenParser
的 ToString()
方法获取已解析的 HTML 并在 Response
对象中返回它即可。
Using the Code
TokenParser 类
TokenParser
定义了一个委托,用于将找到的标记传递给调用代码。当解析器遇到标记时,它会调用 OnToken
事件,并将标记和一个引用的字符串传递给已实现的 TokenHandler
,该处理程序会将所需的值放置到其中。
// ********************************************************************************
// Document : TokenParser.cs
// Version : 0.1
// Project : StrayIdeaz
// Description : This is a very simple HTML template parser. It takes a text file
// and replaces tokens with values supplied by the calling code
// via a delegate.
// Author : StrayVision Software
// Date : 7/20/2008
// ********************************************************************************
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace TemplateParser
{
/// <summary />
/// TokenParser is a class which implements a simple token replacement parser.
/// </summary />
/// <remarks />
/// TokenParser is used by the calling code by implementing an event handler for
/// the delegate TokenHandler(string strToken, ref string strReplacement)
/// </remarks />
public class TokenParser
{
private String inputText;
private String textSourceFile;
public delegate void TokenHandler(string strToken, ref string strReplacement);
public event TokenHandler OnToken;
构造函数接受要解析的源文件的路径和名称。
public TokenParser(String sourceFile)
{
textSourceFile = sourceFile;
}
ExtractToken
解析格式为 "[%TOKENNAME%]" 的标记。它不知道标记的含义,只知道它是由 [% 和 %] 括起来的字符串。它返回这两个标记之间的字符串。
private string ExtractToken(string strToken)
{
int firstPos = strToken.IndexOf("[%")+2;
int secondPos = strToken.LastIndexOf("%]");
string result = strToken.Substring(firstPos, secondPos - firstPos);
return result.Trim();
}
Parse()
遍历类变量 inputText
的每个字符。 inputText
代表要解析的 HTML 文件的内容。 Parse()
返回一个字符串,表示 inputText
,其标记已替换为调用代码的值。
private String Parse()
{
const string tokenStart = "[";
const string tokenNext = "%";
const string tokenEnd = "]";
String outText = String.Empty;
String token = String.Empty;
String replacement = String.Empty;
int i = 0;
string tok;
string tok2;
int len = inputText.Length;
while (i < len)
{
tok = inputText[i].ToString();
if(tok == tokenStart)
{
i++;
tok2 = inputText[i].ToString();
if (tok2 == tokenNext)
{
i--;
while (i < len & tok2 != tokenEnd)
{
tok2 = inputText[i].ToString();
token += tok2;
i++;
}
OnToken(ExtractToken(token), ref replacement);
outText += replacement;
token = String.Empty;
tok = inputText[i].ToString();//i++;
}
}
outText += tok;
i++;
}
return outText;
}
Content()
方法只是读取 HTML 文件并返回其未更改的文本。如果您编写了一个应用程序,其中包含教程,并且您想显示未解析的 HTML 以演示模板中标记的使用,这很有用。
/// <summary />
/// Content() reads the text file specified in the constructor
/// and returns the unparsed text.
/// </summary />
/// <returns />
/// A string representing the unparsed text file.
/// </returns />
public String Content()
{
string result;
try
{
TextReader reader = new StreamReader(textSourceFile);
inputText = reader.ReadToEnd();
reader.Close();
result = inputText;
}
catch (Exception e)
{
result = e.Message;
}
return result;
}
现在,我们来讨论重要的方法:ToString()
。实现 OnToken
事件后,您调用 ToString()
来执行实际的解析,并获取已解析的 HTML 文本,其中填充了您的值。
/// <summary />
/// This is called to return the parsed text file.
/// </summary />
/// <returns />
/// A string representing the text file with all its tokens replaced by data
/// supplied by the calling code through the Tokenhandler delegate
/// </returns />
public override string ToString()
{
//TextReader reader;
string result;
try
{
TextReader reader = new StreamReader(textSourceFile);
inputText = reader.ReadToEnd();
reader.Close();
result = Parse();
}
catch (Exception e)
{
result = e.Message;
}
return result;
}
}
}
现在我们已经看到了 TokenParser
类,让我们来看看如何使用它。下面列出了一个 ASP.NET 代码隐藏页面的完整源代码,该页面实现了 TokenParser
。
声明了两个类级别的私有变量:String pageText
,它将保存已解析的 HTML 文本,以及 TokenParser parser
,这是我们的 TokenParser
对象。在 Page_Load
事件中,我们获取了模板文件的路径(这可以是您想要的任何路径和文件名)。然后,我们调用 LoadPage()
来完成工作。
还要注意的是,我们实现了一个名为 OnToken
的方法。这是我们的事件处理程序。您可以将其命名为任何您想要的名称,只要它接受两个参数:string
和 ref string
。在这个事件中,替换标记为有意义的值的工作就完成了。
这些标记可以被称为您想要的任何名称:[%MYVAR%]
, [%FOOBAR%]
, [%LATESTNEWS%]
等等。根据传递的标记,您在 ref string
中发回 HTML 代码、JavaScript 或您想要的任何文本。
LoadPage()
是我们示例中的最后一个方法。这是实例化 parser
对象、分配 Ontoken
事件,以及调用 parser.ToString()
方法以检索我们已解析的 HTML 模板的地方。从那里,只需通过 Response.Write()
将其发送到用户的浏览器即可。
public partial class _Default : System.Web.UI.Page
{
private String pageText;
private TokenParser parser;
protected void Page_Load(object sender, EventArgs e)
{
string path = Server.MapPath("template.html");
LoadPage(path);
}
public void OnToken(string strToken, ref string strReplacement)
{
if (strToken == "TESTME")
strReplacement = "Moose Butts a-Flyin!";
else
strReplacement = "Huh?";
}
private void LoadPage(string fileName)
{
parser = new TokenParser(fileName);
parser.OnToken += this.OnToken;
pageText = parser.ToString();
DisplayPage();
}
}