xml
仅仅因为知道某些东西是 XML 格式并不意味着可以用一般 XML 语法分析器来理解输入。尝试将来自木星卫星的光谱数据塞进公司的记帐程序中也许是有趣的,但这会惹恼会计。这可能象剪切 Apache 配置文件并将它粘贴到图形程序中。公共的数据格式是了不起的,但语法标准不暗示所有程序能够理解所有数据。
XML 是差的人机界面
直到现在,我只讨论了程序间用于交谈的数据格式。除了前面部分中的告诫,对于大多数程序对程序数据格式需求,XML 应该是一个安全的赌注。程序、规范、初始化文件以及类似于人机之间的对话一类东西又怎样呢?在这一节中,我希望使您信服人们不一定必须编写和充分理解 XML。与许多提供优秀界面的现有标准专用语言相比,XML 大概离您能得到的自然人类语言还差得很远吧。
我的论点很简单:人类具有将结构应用到字符串(句子)的天生能力,所以,添加标记符号只能使我们阅读更困难,输入更吃力。问题是,在设计和对计算机语言进行语法分析方面,大多数程序员没有什么经验。与其把时间花在设计和分析人类友好的语言上,程序员倒不如使用最快的路径来提供规范语言和实现:“哦,用 XML。就这样吧。”并且那也不错,但我希望程序员认识到,当他们走那种捷径时,他们正在提供一种较差的界面。不相信我?在本文余下部分中,我将一对一地比较专门针对人类的语言和他们不自然的 XML 结构化的等价物。
让我们从一个简单的算术表达式开始。人类已使用至少有一千年的专用语法,与 XML 语言相比,哪个更易于读和写呢?
数学 XML 语法
3+4*5 <add>
<int>3</int>
<mult>
<int>4</int><int>5</int>
</mult>
</add>
的确,3+4*5 更容易读和写。人类已经精确地构建了专门的领域特定的语言,来有效地使用这些语言描述问题(注意,有大量专用编程语言,如 PostScript、PERL、Mathematica,等等)。上述 XML 规范是表达式的语法分析树(结构)表示 - 记得句子结构图吗?在处理之前,语言语法分析器将输入转换成语法分析树,因为明确的语法分析树要比易于人类理解的隐式句子结构更易于计算机处理。输入明确的结构避免了在程序中需要专门语法分析器,但这给用户添加了大量负担。
免得您认为表达式太简单而不能成为适合的示例,请考虑我设计和实现的、从 jGuru 的对象数据库抽取数据的定制的查询语言。清单 1 是一个简单查询。
清单 1. 没有用 XML 格式的简洁查询
query type Person props (email,firstname,lastname) where "EID>100"
人类当然喜欢输入简洁的一行查询语句,而不是清单 2 中等价的 XML。
清单 2. XML 格式的同一个查询 <query>
<type>Person</type>
<props>
<prop id="email"/>
<prop id="firstname"/>
<prop id="lastname"/>
</props>
<cond>
<gt>
<prop id="EID"/>
<int>100</int>
</gt>
</cond>
</query>
自然地,专门的语法分析器在内存中将查询转换成树状结构,该结构就象 XML。我要说的是,人类输入简单查询,而计算机做明确地演算该结构的工作。请注意,该查询结果,一组对象,以序列化的 XML 数据被送回客户机,因为它表示程序对程序通信,并且它是 XML 极适合的使用。
更大的规范又怎样?使用面向人类的语言,它们更容易理解。考虑课程描述符文件,我们在 jGuru 上用它将各种课程模块组合成一个完整的课程。清单 3 显示了 JavaIntro 课程的简短描述。
清单 3. Java 介绍课程的简短非 XML 描述
course JavaIntrocourse {
title = "Java Language Essentials"
caption = "Core features of the Java programming language"
mmlvers = "2"
content {
intro = "intro.mml"
variables = {useApplets="false", genTM="true", genIBM="true"}
modules = { "JavaIntro.mod", "vsCOBOL.mod" }
}
}
描述中有许多信息,但真正只是一串赋值语句和字符串列表。甚至非程序员也能看懂其基本含义。我猜想,清单 4 中的等价 XML 可能会给大多数非程序员带来理解性问题。
清单 4. 清单 3 的 XML 等价
<course>
<title>Java Language Essentials</title>
<caption>Core features of the Java programming language</caption>
<mmlvers>2</mmlvers>
<content>
<intro>intro.mml</intro>
<variables>
<var id="useApplets">false</var>
<var id="genTM">true</var>
<var id="genIBM">true</var>
</variables>
<modules>
<module>JavaIntro.mod</module>
<module>vsCOBOL.mod</module>
</modules>
</content>
</course>
当然,甚至对于程序员,该 XML 规范要比传统的规范更难以阅读。有如此之多的 XML“噪音”干扰,以至于数据不会再跳至您面前。是的,如果有经验的话,读 XML 会容易些(当我为工业机器人编写设备驱动程序时,我甚至擅长于阅读十六进制内存转储),但您宁愿输入哪一个呢?您可能习惯于任何事,但当有对人类更友好的替代物时,为什么还必须习惯于难于理解的对计算机友好的数据呢?
值得一提的是,我们用一种符合 XML 的类 HTML 标记语言来编写实际的课程模块文本,因为我们需要在英语散文中嵌入可清晰地有别于英语的结构。没有标记语言,模块语法分析器就不能区分课程内容与各部分标记等等。有时,很难阅读原始的模块源码(同样还是因为 XML“噪音”干扰),但没有其它特定领域的嵌入式语言可适用。
对于许多规范问题,自然语言,如英语,提供了最自然的书写界面。遗憾的是,自然语言是模糊的并且极难识别。然而,花少许功夫,就可以定义明确但仍不失简捷的简化子集。考虑一种冒险游戏语言,其中您可能说:
Tease the nice velociraptor
任何讲英语的人都能够分析上述句子,即使他们从来没有听说过 velociraptor。相反,如果必须输入如清单 5 所示的内容,那么您愿意如何玩这样的游戏呢?
清单 5. Tease the nice velociraptor 的 XML 表述
<command>
<verb>Tease</verb>
<object>
<article>the</article>
<nounmodifier>
<adjective>nice</adjective>
<noun>velociraptor</noun>
</nounmodifier>
</object>
</command>
哇!多么令人信服。人类从来不需要也不希望标记结构标记来使人易于理解句子。当输入时,我想说“Tease the nice velociraptor”。另一方面,当游戏记录我的命令历史时,它可能以 XML 存储各条命令来防止必须重新对这些命令进行语法分析。
我将用类似的另一种人机界面语言来结束我的论点:人类说话。对于计算机程序,观看数字化说话信号(数字流),尝试抽取英语单词序列是极其困难的。另一方面,人类已经进化了超过数百万年,可以毫不费力地理解语言,因而我们发现它是特别令人满意的界面。对说话的自然方式的任何变动都会降低界面的效果。设想必须通过向一个简单的识别程序提供额外信息来“标记”您的说话。遗憾的是,早期商业语音识别程序确实需要您如此:必须在口头讲的字之间停顿!这些停顿去除了字边界的不确定性 - 最大问题之一 - 通过明确地说等价的:
<word>stupid</word><word>computer</word>
对人机语言使用 XML 标记类似于在口头讲的字之间的停顿,并且是令人不愉快的。
结束语
虽然 XML 是重要的和复杂的标准格式,但它只是另一种数据格式。在大多数情况下,用 XML 格式来存储或发送数据是有意义的,但有一些例外: