这篇技巧文章示范了如何用一种简单的开放源代码工具 HTML Tidy,将 HTML 文档转换成 XML(更确切地说是 XHTML)。这种转换对于要将网站迁移到 XML 上去的网管来说是很有用的。同时那些需要与以前的 HTML 工具交互的 XML 转换工具也能从中获益。
当网管们要将网站从单纯的 HTML 转换到 XML/XSL 上的时候,需要面临的挑战之一就是如何保留原有的 Web 站点。因为如果要是将老的站点全部抛弃,重新开始设计新站点,付出的代价就太大了。所以,人们需要一种自动化的手段,将 HTML 站点带入 XML 时代。
即便对于 XML 转换工具而言,依然需要处理 HTML 文件:很多产品都提供了可以将文件导出为 HTML 文档的选项。您可能也会希望将这种选项集成到您的 Web 站点中。
这篇技巧文章讨论的 HTML Tidy 是一种功能强大的工具,它可以帮助您将旧的 HTML 页面转换到新的标准上,比如 XML。Tidy 的分发方式是开放源代码。
当您将站点从 HTML 升级到 XML 的时候,所需要的基本工具就是 HTML Tidy。HTML Tidy 最初的开发者是 Dave Raggett,并通过 W3C 网站以开放源代码许可协议分发。HTML Tidy 现在是由 SourceForge 上的一群志愿人员在维护。它还有基于 Java 语言的版本(或许称之为 JTidy 更加合适些),参阅 参考资料。目前来讲,其中至少还包括一组 API,使您能够将 HTML Tidy 作为类库集成到您自己的应用程序之中。
HTML 和 XML 都是从 SGML 派生出来的标记语言,因此两者有很多共通的地方。但是,它们之间有两个最主要的区别:
- XML 的语法限制性更强;在 XML 中最主要的一点就是,您必须记住要写结束标记。
- 编写 HTML 代码的时候通常可以相对粗心一些,因此 HTML 文件很少有没有错误的。
早期的 Web 浏览器容错性很强,因此网管当中滋生出一些草率的习惯。在那个时候,浏览器的目标是吸引尽可能多的用户,并鼓励网管发布更多的网页。这种策略十分奏效,Web 上的内容开始以指数级的速度增长。
然而,糟糕的编码习惯引发了各种各样不兼容的情况。HTML Tidy 最初的设计目标就是解决这样的问题。它通过重写 HTML 页面,以顺应最新的 W3C 标准。在这个过程中,HTML Tidy 解决了包括标记不完整在内的很多常见错误。
尽管 HTML Tidy 最初是用于处理 HTML 页面的,但是它也支持 XHTML 这一 XML 词汇表。
让我们举个例子。我将会处理一个由 Photoshop 生成的照片库。您也可以使用其他的 HTML 文档,但是如果您想采用和我一样的文件,可以从 参考资料 中找到图片库的下载链接。清单 1 是从图片库中节选的一部分文档。您可以看到,里面用的是普通的 HTML 代码。
<HTML> <HEAD> <TITLE>Journey to Windsor</TITLE> </HEAD> <BODY> <TABLE> <TR> <TD width=15></TD> <TD><FONT size="3"face="Helvetica"> Journey to Windsor<BR> Benoît Marchal<BR> July 2003<BR> <BR> <A href="mailto:bmarchal@pineapplesoft.com"> bmarchal@pineapplesoft.com</A> </FONT></TD> </TR> </TABLE> <CENTER><TABLE border=3> <TR><TD> <A href="pages/dscn0824.html"> <IMG src="thumbnails/dscn0824.jpg" border="0" alt="dscn0824"> </A><br> <FONT size="3" face="Helvetica"> dscn0824.jpg<br> A bright, red mailbox inside the castle. It seems oddly familiar in an historic setting.<br> Windsor Castle <br> © 2003, Benoît Marchal </FONT> </TD></TR> </TABLE></CENTER> </BODY> </HTML>
显然,第一步是下载并安装 HTML Tidy(您可以从 参考资料 中找到相关链接)。HTML Tidy 有很多操作系统上的版本,包括 Windows、Linux 以及 MacOS。缺省的可执行程序是一个命令行工具,Windows 和 MacOS 上有 GUI 版本。
运行 HTML Tidy 的方法是,打开终端,输入下面的命令:
tidy -asxhtml -numeric < index.html > index.xml
太棒了!HTML Tidy 立刻将 index.html 转换成了 index.xml。HTML Tidy 会在输出信息中把转换过程中对原始的 HTML 文档所作的处理以高亮显示出来。在大多数情况下,您可以放心地忽略这些消息。
HTML Tidy 是作为过滤器运行的,因此它希望从标准输入设备获得数据,并将处理结果打印到标准输出设备上。重定向操作符(< 和 >)可以用于处理文件。缺省条件下,HTML Tidy 产生的是一个干净的 HTML 页面,不过您也可以通过设置如下两个选项来输出 XML:
-asxhtml
输出的是 XHTML,而不是 HTML。-numeric
用字符实体取代 HTML 实体。比如,用î
取代î
。
XHTML 和 HTML 之间的差距听起来好像微不足道(毕竟两者的名字上只是多了一个“X”而已),但是这个 X 却是很重要的。XHTML 是 HTML.4.01 的版本之一,已经符合 XML 的语法。词汇表没有变化(XHTML 使用的也是您所熟悉的标记,如 <p>、
<b>
、和 <a>
),但是语法却是 XML 的,因此可以很好地融入 XML 的处理流程之中。
HTML 和 XHTML 之间的主要区别在于:
- XML 元素必须有开始和结束标记,而 HTML 对于很多元素都不要求有结束标记,如
当
<p>
是空元素的时候就不要求使用结束标记。 - 空元素遵循 XML 的规范。比如说,换行符写为
<br />
,而不是<br>
。 - 属性值一定要用引号引起来(比如说,要写成
<a href="http://www.marchal.com">
,而不能写成<a href=http://www.marchal.com>
)。
清单 2 是 HTML Tidy 对清单 1 所示的输入数据处理得到的文件。从中您可以看到,这是一个合法的 XML 文档,而且,为了生成它所做的工作是很少的。
XPaths 与空元素 清单 2. index.xml (节选)您在用 XSL 处理 XHTML 文档的时候必须小心。XHTML 主要是一种格式化的语言,XHTML 不像其他的 XML 词汇表,它几乎不会对结构造成什么变化。如果要恢复结构,您必须对文档进行分析,仔细地取出适当的 XPaths。在本例中,我们并不能一下子就看出如何将图像的标题与它的描述分开:这两者之间只有一个<br/>。因为换行标记是空标记,因此用它来获取文本并不充分!最终,我通过 preceding-sibling
轴将空标记之前的文字加载进来。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta name="generator" content= "HTML Tidy for Mac OS X (vers 1st June 2003), see www.w3.org" /> <title>Journey to Windsor</title> </head> <body> <table> <tr> <td width="15"></td> <td><font size="3" face="Helvetica">Journey to Windsor<br /> Benoît Marchal<br /> July 2003<br /> <br /> <a href= "mailto:bmarchal@pineapplesoft.com">bmarchal@pineapplesoft.com</a></font></td> </tr> </table> <center> <table border="3"> <tr> <td><a href="pages/dscn0824.html"><img src= "thumbnails/dscn0824.jpg" border="0" alt="dscn0824" /></a><br /> <font size="3" face="Helvetica">dscn0824.jpg<br /> A bright, red mailbox inside the castle. It seems oddly familiar in an historic setting.<br /> Windsor Castle<br /> © 2003, Benoît Marchal</font></td> </tr> </table> </center> </body> </html>
要是您觉得 XHTML 的词汇看起来不舒服,那该怎么办呢?请您接着往下读。
XHTML 文档是有效的 XML 文档,因此您可以将它们加入到 XML 的处理流程中。更确切地说,您可以用常规的 XML 工具(如 XSL、解析器,等等)再对这些文件进行处理。
事实上我并不是非常喜欢这个例子中用到的 XHTML 词汇表。因为 XHTML 是用于发布的词汇表,因此结构性很差,我希望通过清单 3 中所示的那种 XML 词汇表来维护我的照片库(这个词汇表最早是在我的技巧文章 Divide and conquer large XML documents 中介绍的)。为了阐明 XML 处理过程,我编写了一个简单的 XSL 样式表(见 清单 4),它可以从 XHTML 文档中获取标题、文件名、日期以及描述信息。这个样式表生成了一个更加结构化的文档,使得我们处理起来更加方便。
清单 3. index-transform.xml (节选)<?xml version="1.0" encoding="MacRoman"?> <gl:gallery xmlns:gl="http://ananas.org/2003/tips/gallery"> <gl:title>Journey to Windsor</gl:title> <gl:photo> <gl:title>Windsor Castle</gl:title> <gl:date>July 2003</gl:date> <gl:image>dscn0824.jpg</gl:image> <gl:description>A bright, red mailbox inside the castle. It seems oddly familiar in an historic setting.</gl:description> </gl:photo> </gl:gallery>
<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:gl="http://ananas.org/2003/tips/gallery" xmlns:html="http://www.w3.org/1999/xhtml" exclude-result-prefixes="html"> <xsl:output method="xml" indent="yes" encoding="MacRoman"/> <xsl:template match="html:html"> <xsl:variable name="date" select="html:body/html:table/html:tr/html:td[2] /html:font/html:br[3] /preceding-sibling::text()[1]"/> <gl:gallery> <gl:title> <xsl:value-of select="html:head/html:title"/> </gl:title> <xsl:for-each select="html:body/html:center/html:table /html:tr/html:td"> <xsl:variable name="title" select="html:font/html:br[3] /preceding-sibling::text()[1]"/> <xsl:variable name="image" select="html:font/html:br[1] /preceding-sibling::text()[1]"/> <xsl:variable name="description" select="html:font/html:br[2] /preceding-sibling::text()[1]"/> <gl:photo> <gl:title><xsl:value-of select="normalize-space($title)"/></gl:title> <gl:date><xsl:value-of select="normalize-space($date)"/></gl:date> <gl:image><xsl:value-of select="normalize-space($image)"/></gl:image> <gl:description><xsl:value-of select="normalize-space($description)"/></gl:description> </gl:photo> </xsl:for-each> </gl:gallery> </xsl:template> </xsl:stylesheet>
HTML Tidy 属于那种很灵巧的小工具,每一个网管的工具箱里都应该有一个。因为它可以输出 XHTML,因此对于那些使用 XML/XSL 的网管是格外有用的。至于其他的词汇表,则只是另一种样式表而已。
- 您可以参阅本文在 developerWorks 全球站点上的 英文原文.
- 下载本文的 源代码,其中包括作者提供的照片库。
- 从 SourceForge 下载 HTML Tidy。它可以在 Windows、Linux、MacOS 以及其他一些平台上运行。同一个网站上还有它的图形化界面以及开发库,这有助于您将其嵌入处理流程中。您还可以下载到 Java 语言版的 JTidy。
- 请访问 Dave Raggett's Web site,这里是 HTML Tidy 最初的家,上面有大量的信息。
- 请阅读 Benoit Marchal 的 利用 XML 进行 Web 发布的基础知识 (developerWorks,2003 年 7 月),文中循序渐进地讲述了用 XML 和 XSL 进行 Web 发布的方法。
- 本文作者在 对大型 XML 文档分而治之一文介绍了如何用样式表发布在线图库( developerWorks,2003 年 6 月)
- W3C 的 HTML 主页上有关于 XHTML 的更多信息。
- 有关 XHTML 更深入的探讨,请阅读 Nicolas Chase 撰写的文章 Web 的未来:XHTML 2.0( developerWorks,2002 年 9 月)。
- 请到 developerWorks XML 专区上查找更多的 XML 资料。要获得到目前为止的所有的 XML 技巧文章,请访问 技巧专栏总结。
- IBM 的 DB2 数据库不仅支持关系数据库存储,也提供与 XML 有关的工具,比如可作为 XML 与关系系统之间桥梁的 DB2 XML Extender。要学习有关 DB2 的更多知识,请访问 DB2 开发者园地。
- 请了解如何成为一名 IBM 认证的 XML 及相关技术的开发人员。
![]() | ||
| ![]() | Benoit Marchal 是一名来自比利时的顾问。他是 XML by Example 一书,以及其他几本 XML 书籍的作者。Benoit 能够给您的 XML 项目提供帮助。您可以通过 mailto:bmarchal@pineapplesoft.com?cc= 与 Benoit 取得联系。 |