IBM®
跳转到主要内容
    中国 [选择]    使用条款
 
 
Select a scope:Search for:    
    首页    产品    服务与解决方案     支持与下载    个性化服务    
跳转到主要内容

developerWorks 中国  >  XML | Java technology  >

XML 和 Java 技术: 溯本追源

回归 XML 的基础,掌握良好的文档结构

developerWorks
文档选项

未显示需要 JavaScript 的文档选项

讨论


级别: 初级

Brett D. McLaughlin, Sr. (brett@newInstance.com), 作家兼编辑, O'Reilly Media, Inc.

2007 年 12 月 06 日

Brett McLaughlin 回顾了一些 XML 基础知识,从文档结构到久存争议的属性/元素问题。重新学习如何优化 XML 并确保拥有最佳结构。

到目前为止,我撰写了很多关于 XML 及相关内容的文章和书籍,当回头重新审视这些文字的时候,结果却令我很吃惊。虽然我是一位程序员,喜欢深入到比特和字节(上大学的时候非常喜欢汇编语言),喜欢那种绝对控制的感觉,但总的来看,我的文章、技巧和著作关于 XML 本身讨论得越来越少,关于操作 XML 的 API、包装这些 API 的 API 以及根本不触及 XML 的其他 API 讨论得越来越多。

因此结果就是一个共性的问题:是否还记得如何实际编写好的 XML 文档?还知道如何区分 XML 好坏的标准么?本文回顾了几篇 XML 101 技巧系列的文章,希望我们在拥有各种工具的同时不会遗忘那些基本的原理。

第一步:正确使用不同的 XML 成分

最突出的显著问题之一是 XML 作者(从宽泛的意义上讲)将各种各样的内容都填塞到元素中。属性、处理指令 — 变成了过去时。

元素

元素在 XML 中最容易使用,很大程度上是因为 XML 作者倾向于完全 依靠元素。当然,这是错误 的,而且有很严重的副作用。XML 中的元素最适合表示具有某种层次结构或者可能 具有某种层次结构的数据(当然也有例外,不过这里讨论的是最佳用法)。首先举一个反例,人名(不含姓和中间名等)永远不可能有层次结构,它就是一个单词,如此而已。但是如果选择使用 name 元素,可能 也不错:至少能分解成名和姓,可能还有中间名、头衔和其他成分。因此下面这样使用元素实际上是不正确的:

<firstName>Bob</firstName>

应该用:

<name firstName="Bob"
 lastName="Zemeckis"
 title="Mr." />

如果还不明白为何不在 name 元素中嵌套 firstNamelastName 以及 title 元素,请仔细阅读 上一段。下一节介绍 属性 时还将进一步讨论。

一般而言,如果一个元素不可能在文档的同一个地方出现多次(比如可能有家庭和办公两个不同类型的 address 元素,图书可能存在两个 author 元素),则应尽量使用属性。并不是说每次使用元素时都必须 出现两次,仅仅是可以 出现两次。

元素最适合文本数据这种说法也不正确,很多例子中元素只有属性而没有文本内容(建议阅读讨论属性的 下一节)。最重要的是要记住 XML 不仅仅 有元素,还有其他结构。

属性

尽管看起来像是废话,但无论如何只能对单值数据使用 XML 属性。比方说,如果使用关于人的元素,那些关于这个人的单值信息就是潜在的属性。社会保障号码、ID,可能还有出生日期 — 都是合适的候选属性。

当然和其他规则相比,属性规则有更多的例外。实际上,我认为属性的应用和应该达到的程度相比少得多。开发人员往往喜欢元素比较清晰的外观:

<person>
 <ssn>489098723</ssn>
</person>

但是这样做毫无意义 — 社会保障号码绝对是单值数据。更糟的是,这样把数字当成元素会影响性能。像这种情况下访问元素的子元素时,必须首先取得元素节点然后遍历所有的子元素节点。社会保障号码可能是第一个节点,但也可能是最后一个节点,不能确定。得到那个 节点的子元素后再访问其值,该例中包括一个文本节点。中间要经过多个步骤:

  1. 获得父节点(person 元素)。
  2. 访问父节点的子节点。
  3. 迭代寻找需要的子节点(ssn 元素)。
  4. 可能需要规范化这个新元素的文本节点以简化后续操作。
  5. 得到元素的子节点。
  6. 取得文本子节点的值。

使用属性的话就简单多了:

  1. 访问父节点(person 元素)。
  2. 访问属性。
  3. 迭代寻找需要的属性(ssn)。
  4. 取得属性值。

这种方法避免了规范化(属性只能有单一的文本值),也不需要处理子元素。我发现访问元素的属性几乎总比访问特定的子元素快。因此性能上的优势很明显,特别是对于成千上万次迭代的情况。

我的观点是,尽管看起来不太好看,XML 应这样使用:

	    <person ssn="489098723"
	            firstName="Bobby"
	            lastName="McKenza"
	    >
	      <occupation>
	        <occupation-type status="part-time"
	                         job="author" />
	        <occupation-type status="part-time"
	                         job="programmer" />
	      </occupation>
	      <address type="home"
	               street="112 E. Harney Way"
	               city="New York"
	               state="NY"
	               zip="10012" />
	      <!-- etc... -->
	    </person>

对大多数人来说可能有点奇怪,因为基本上所有信息都用属性表示。但是我相信这种方法更好,访问 10,000 或更多次时能够可观地提高效率(访问次数多可以将细微的性能改进叠加起来)。

处理指令

通常不使用处理指令或者 PI。但是,令人苦恼的是现在很多 XML 处理 API 要求把特殊代码或指令放在注释中、或者使用特殊的名称空间以及各种专用元素,甚至使用包含指令的元素。如果 XML 需要为处理 API 或者工具提供信息,这些信息就是处理指令,XML 有专门的机制。

以前肯定遇到过,特别是在 XSL 中:

<?xml version="1.0"?>
<?xml-stylesheet href="classic.xsl" type="text/html"?>
<?xml-stylesheet href="alternate.xsl" type="text/xml" alternate="yes"?>
<article>
 <!-- etc ... -->
</article>

这里 PI 告诉 XSLT 处理程序应用于 XML 文档的样式表在哪里。不用考虑那些忽略该机制的 API(尽管首先想到的就是 JAXB),应该充分利用该机制,无论如何要比下面这种方法强:

<?xml version="1.0"?>

<!-- xml-stylesheet url="classic.xsl" document-type="text/html" -->
<!-- xml-stylesheet url="alternate.xsl" document-type="text/xml" -->
<article>
 <!-- etc ... -->
</article>

我经常看到这样的代码。注释是没有意义的,使用注释并将其中的信息作为指令处理的 API 是危险的。Javadoc 和文档生成 API 使用注释,但至少作为文档而不是具有实际意义的指令使用。显然,如果选择的 API 要求这种标记,您可能继续使用,但应该认识到这并非按照 XML 本来的方式使用 XML。我相信 XML 规范的作者在这个问题上说得很明确了。





回页首


结束语

分享这篇文章……

digg 提交到 Digg
del.icio.us 发布到 del.icio.us
Slashdot 提交到 Slashdot!

也许我早应该讨论这些问题,但我并不是 XML 纯粹论者。事实上我认为 XML 的很多东西愚蠢无聊、本末倒置或者是完全错误的。但是我的确 认为,既然选择使用 XML,一些基本的概念对于正确使用是必须的,否则何必选择 XML 呢?如果多值数据或者长数据不用元素,如果根本不使用属性,如果滥用或者不用处理指令,某个时候就会发现最好离开 XML 去编写自己的私有语言或解析器来处理您的数据。否则就得忍受 XML 的枷锁 — 冗长、奇形怪状的文档、编码问题等等 — 而没有任何好处 — 专用的高速解析器。

因此不要为了正确地使用 XML 或者取悦语义主宰者而考虑这些建议。对于您的编程生涯来说这些都不是恰当的理由。如果将其看作更有效地利用 XML、提高软件性能的办法,就是合情合理的了。继续前进吧,打破那些规则 —— 但必须有充分的理由!



参考资料

学习
  • 您可以参阅本文在 developerWorks 全球网站上的 英文原文

  • Sun 的在线 Java™ and XML Headquarters 是学习 JAXP 的最佳地方。

  • Java 5.0 技术 核心 API 文档:看看 JAXP JavaDoc 是如何集成到该 API 之中的。

  • SAX 网站:进一步了解 JAXP 环境下的这种 API。学习 Java 环境中的 SAX 2。

  • W3C 网站:关于 SAX 支持 XML 的其他观点,看看 DOM。

  • XML 入门教程(Doug Tidwell,developerWorks,2002 年 8 月):如果需要了解 XML 的基础知识,请阅读该教程和其他入门性的 XML 教程

  • IBM XML 认证:看看如何才能成为一名 IBM 认证的 XML 及相关技术的开发人员。

获得产品和技术
  • Apache Xerces 解析器:了解 Sun 用于 JDK 5.0 实现的这种解析器。


讨论


关于作者

Photo of Brett McLaughlin

Brett McLaughlin 从 Logo 时代就开始使用计算机。(还记得那个小三角吗?)近年来他已经成为 Java 技术和 XML 社区最知名的作家和程序员之一。他曾经在 Nextel Communications 实现过复杂的企业系统,在 Lutris Technologies 编写应用程序服务器,最近在 O'Reilly Media, Inc. 继续撰写和编辑这方面的图书。在他的新书 Head Rush Ajax 中,Brett 与畅销书作家 Eric 及 Beth Freeman 为 Ajax 带来了获奖的创新方法 Head First。他的上一本书 Java 1.5 Tiger: A Developer's Notebook 是第一本可获得的关于最新版本 Java 技术的书籍,而他的经典著作 Java and XML 仍然是在 Java 语言中使用 XML 技术的权威图书。




对本文的评价

太差! (1)
需提高 (2)
一般;尚可 (3)
好文章 (4)
真棒!(5)

将您的建议发给我们或者通过参加讨论与其他人分享您的想法.




回页首


Java 和所有基于 Java 的商标都是 Sun Microsystems, Inc. 在美国和/或其他国家的商标。 其他公司、产品或服务名称可能是其他公司的商标或者服务标记。 其他公司、产品或服务的名称可能是其他公司的商标或服务标志。

IBM 公司保留在 developerWorks 网站上发表的内容的著作权。未经IBM公司或原始作者的书面明确许可,请勿转载。如果您希望转载,请通过 提交转载请求表单 联系我们的编辑团队。
    关于 IBM 隐私条约 联系 IBM 使用条款