### XML 加 ASP 实现网页“本地化”

想让你的站点能被来自多个国家的冲浪者看明白吗？无疑，这就需要提供多个语言版本的页面内容，也就是所谓的“本地化”功能。最容易想到的方法就是分别编写多种语言的页面内容，然后放置到不同的目录下，再在首页上添加导航到各自语言位置的链接。很明显，这样的处理方式将浪费许多包含公共元素以及设计框架的空间，而且修改、维护也很烦琐。有什么好方法吗？当然，本文就介绍如何结合使用 XML 与 ASP 技术实现这个目的。
本文将讨论如下几个方面的内容：创建包含语言资源的 XML 文档、使用 ASP 创建 Web 页面模板、使用 XPath 语法和 MSXML3 分析器定位 XML 文档中的目标内容以及动态地在 HTML 流中插入语言字符串。
准备条件
本文讨论的技术涉及到以下方面：IIS4 或者 PWS（包含 ASP 功能），MSXML 版本 3。
功能展示
本文要讨论的例程是一个简单的 HTML 表单，用以提交名字和地址信息。下面是在 Netscape Navigator 中显示西班牙语言的图示：
采用本文论述的技术，你就可以非常简单地通过更新一个 XML 文件实现为站点添加多种语言的功能。
创建包含语言资源的 XML 文档
首先，使用喜爱的页面编辑器创建一个叫做 xmltrans.asp 的 Web 页面文件。我发现使用静态占位符文字（比如"First name "）设计页面最容易。当 XML 准备好后，就可以使用变量替换这些静态文字。要下载例程文件请点击这里。
完成基本页面的功能设计后，开始创建一个包含语言字符串的良好格式 XML 文档。在这里，我使用纯文本编辑器 Notepad 编写初始的 XML 语言集－英语版本。Notepad 使我感觉更接近于源代码。XML 文件命名为 xmltrans.xml。下面列出了包含 English、French 和 Spanish 字符串的 XML 文件代码内容：
<?xml version="1.0" encoding="UTF-8"?>
<languages>
<language xml:lang="en" engname="English" langname="English" charset="Windows-1252">
<title>Localize ASP with XML</title>
<firstname>First name</firstname>
<lastname>Last name</lastname>
<prefix>Prefix</prefix>
<suffix>Suffix</suffix>
<address1>Address</address1>
<address2>Address 2</address2>
<address3>Address 3</address3>
<city>City</city>
<region>State/Province</region>
<postalcode>Postal code</postalcode>
<areacode>Area code</areacode>
<telephone>Telephone number</telephone>
<submit>OK</submit>
<lang>en</lang>
<charset>Windows-1252</charset>
<langname>English</langname>
</language>
<language xml:lang="fr" engname="French" langname="franζais" charset="Windows-1252">
<title>Localize ASP with XML - French</title>
<firstname>Prénom</firstname>
<lastname>Nom</lastname>
<prefix>Préfixe (M., Mme, Mlle)</prefix>
<suffix>Suffixe/Titre</suffix>
<address1>Rue</address1>
<address2/>
<address3/>
<city>Ville</city>
<region>Région/Province</region>
<postalcode>Code postal</postalcode>
<areacode>Indicatif régional</areacode>
<telephone>Numéro de téléphone</telephone>
<submit>OK</submit>
<lang>fr</lang>
<charset>Windows-1252</charset>
<langname>French</langname>
</language>
<language xml:lang="sp" engname="Spanish" langname="Espanol" charset="Windows-1252">
<title>Localize ASP with XML - Spanish</title>
<firstname>Nombre</firstname>
<lastname>Apellido paterno</lastname>
<prefix>Prefijo (Sr., Sra., Srta.)</prefix>
<suffix>Sufijo o título</suffix>
<address1>Línea 1 de dirección</address1>
<address2/>
<address3/>
<city>Ciudad</city>
<region>Región, estado o provincia</region>
<postalcode>Código postal</postalcode>
<areacode>Código de área</areacode>
<telephone>Número de teléfono </telephone>
<submit>OK</submit>
<lang>sp</lang>
<charset>iso-8859-1</charset>
<langname>Spanish</langname>
</language>
</languages>
xmltrans.xml 文件的第一行是 XML 声明。其中的 version 属性告诉读者文档符合 XML 1.0 的标准，encoding 属性指示解析器使用压缩版本的 Unicode：
<?xml version="1.0" encoding="UTF-8"?>
一个 XML 文档需要一个包含其他元素的根元素。因为这里的例程是包含一些语言，所以就命名根元素为 languages：
<languages>
作为集合类型，languages 元素包含了一个或多个 language 元素：
<language xml:lang="en" engname="English" langname="English" charset="Windows-1252">
以上 language 标记包含 4 个属性。xml:lang 属性是其中最重要的，在 ASP 程序中将通过这个属性值的 2 字母语言代码搜索字符串组。其他的属性，比如 charset，可以为将来的功能扩充而用。
每种语言节点中，我都添加了一个元素作为变量，其中含有显示在 HTML 页面上的文字。XML 允许使用有含义的名字作为自定义标记，比如，我使用<title>元素包含 HTML 页面的标题。同样，<firstname>元素包含字符串"First name"。
<title>Localize ASP with XML</title>
<firstname>First name</firstname>
最后，良好格式的 XML 文档包含了一整套对应于 HTML 页面的字符串。下图显示了 XML 文件中的标记和 English 语言字符串。注意，现在这里只讨论 English 版本，以后可以添加更多种语言。
ASP 文件代码分析
现在回来看看 ASP 文件 xmltrans.asp。在其中我们使用 XML 路径语言（XPath），它可以在微软的 XML 解析器（MSXML）中执行。你可以认为 XPath 是抵达 XML 文档一部分内容预定位置的工具，这有些类似于在命令行中输入一个路径以执行文件，比如 c:\winnt\notepad.exe，或者在浏览器中敲入了一个 URL 访问页面。下面研究这个 ASP 文件看看如何取回 English 语言字符串。首先，我们实例化一个叫做 MSXML2.DOMDocument 的 XML 解析器工作对象：
set doc=server._
CreateObject _
("MSXML2.DOMDocument")
由于 ASP 程序不能象 Win32 程序一样处理事件，所以在这里我们关闭了异步操作选项。这样就确保了在转向其他任务前，脚本程序会一直等待当前事件的完成：
doc.async = False
接着使用 DOMDocument 对象的 Load 方法装载包含字符串的 XML 文档。如果转载过程中发生了错误，就发出警告信息并停止运行：
if not doc.Load(server._
mappath("xmltrans.xml")) then
msg="Failed to load "
msg=msg & "the XML file"
Response.Write msg
Response.End
end if
我们可以使用两种方法查询 XML 文档：XSL 和 XPath。在这里让解析器使用后者，传递属性名字和正确数值给 setProperty 方法：
doc.setProperty _
"SelectionLanguage", "XPath"
然后，创建选择 XML 文档部分内容的路径。很明显，相关字符串位于 languages 元素的某个位置内，因此 languages 成为路径的最开始部分。同时我们知道字符串是被包含在一个 language 元素内的，但是是哪一个呢？请别忘记在前面的 XML 文档中，我们嵌入了一个叫做 xml:lang 的属性，并给出了一个唯一数值“en”。这就是我们要选择的，下面是操作它的语法：
sel="/languages/language"
sel=sel & "[@xml:lang='en']"
这有些不好理解，但你可以将这段 XPath 代码想像为一个 SQL 语句，类似于取回一个记录集的命令：
SELECT * FROM languages.language WHERE xml:lang='en'
回到现实的 XPath 查询，要使用下面的代码返回包含第一个匹配节点的节点对象：
set selectednode = _
doc.selectSingleNode(sel)
最后一步是传递元素名字("title")给 selectSingleNode 方法，并要求它取回"title"节点的 text 属性值。就是说，取得包含在<title>和</title>的文字。在这里，取回的文字是"Localize ASP with XML"：
txt=selectednode._
selectSingleNode("title").text
与 SQL 命令对照，就象从 ADO 记录集内部取回一个字段值，语句是：
txt=rs("title")
在 ASP 页面中插入语言字符串
知道了如何从 XML 元素中选取文字并赋值给变量，就可以将变量值插入到 HTML 流中了。为了使代码简洁，创建一个叫做 getstring()的函数，如下：
function getstring(instring)
temp=selectednode._
selectSingleNode _
(instring).text
getstring= _
server.htmlencode(temp)
end function
getstring()函数的输入值是元素名，元素值要从 XML 文档中取回。比如，将"firstname"传递给 getstring()，getstring 函数就选择 firstname 元素并返回它的文本数值。为保险起见，在返回给调用者前，我们使用 ASP 的 server.htmlencode 方法转换文本为合法的 HTML 代码。在 ASP 页面中，调用代码类似如下：
<td>
<%=getstring("firstname")%>:
</td>
如果选择了 XML 文档的 English 部分，HTML 输出结果如下：
<td>First name:v/td>
如果选择了 French，HTML 输出结果如下：
<td>Prénom:</td>
下图显示了 French 语言版本的表单：
选择可用语言
XML 的一大优势就是它是以清晰的文本格式保存，我们能够在任何时候更新 Web 服务器上的 XML 文件。而且，我们还可以将 English 版本的 xmltrans.xml 文件在 XML 编辑器 XML NotHPad 中打开，复制一份，然后将其中文字翻译为一种新语言。下图显示了 XML Notepad 中的例程文件：
上图中，在左边可以执行添加、删除以及选择元素和属性的操作，在右边可以编辑相关内容。当站点需要多种语言版本时，只需要在内容中执行粘贴操作，然后上载最新的 XML 文档就可以了。
为了使添加的语言立即生效，要增加一个程序，用它判断文件中不同语言的种类数量，并返回语言代码和语言名称。如下面的代码段所示，我们可以将数据格式化处理以创建一个 HTML 列表框。当用户提交表单时，2 字母表示的语言种类代码被存储到 ASP 会话变量 choselang 中。
<select name="chosenlang">
<%
for i=0 to selectednodes.length - 1
response.write "<option value=" & _
chr(34) & _
selectednodes.item(i)._
selectSingleNode("lang").text & chr(34)
if (selectednodes.item(i)._
selectSingleNode("lang").text = _
session("chosenlang")) then
response.write " selected>"
else
response.write ">"
end if
response.write selectednodes.item(i)._
selectSingleNode("langname").text & _
"</option>" & vbcrlf
next
%></select>
添加提示信息以及字符集数据
上面使用 XML 提供了 HTML 表单的可变语言文字显示，接着还要考虑一些更丰富的用途。比如说，要在选择语言时添加一个提示信息，只需要在文字前后嵌入 HTML 标记<LABEL>，并从 XML 中提供可变内容作为 title 属性值。同理，为了帮助浏览器识别 HTML 页面的语言种类，将字符集信息保存到 XML 文件中，比如：
<charset>x-sjis</charset>
然后，就可以使用 ASP 将字符集类型插入到 HTML 流中：
<meta HTTP-EQUIV="Content-Type" content="text/html; charset=
<%=getstring("charset")%>" />
最后的 HTML 代码包括了 Japanese 字符集参考：
<meta HTTP-EQUIV="Content-Type" content="text/html; charset=x-sjis" />
下图显示了使用 Japanese 字符集的页面。记住，要看到正确的内容，操作系统以及浏览器必须支持 Unicode 并安装了相应字符。否则，就会看到一些奇怪的文字，可能是一些问号，也可能是一些方块符号等等。
总结
本文讲述了如何使用 XML 文件保存 Web 页面的语言字符串。从中我们学会了使用 ASP 脚本程序并借助微软 XML 解析器和 W3C 的 XPath 语言实现查询 XML 文档的功能。ASP 代码将包含字符集类型的可变文字插入到 HTML 流中，并形成列表框以让用户选择可用语言。本文涵盖了许多内容，但我想这只是一个起点。虽然可以在支持 XML 的浏览器中简单地实现这些功能，但我们已经看到：使用服务器端脚本可以转换 XML 数据为普通的 HTML 内容，即使是早期版本的浏览器，同样能够看到这些精彩内容。