Dive Into HTML5:可扩展性

HTML5 有超过 100 个元素。有些是纯语义的,有些则是脚本 API 的容器。回顾 HTML 的历史,标准化工作的重要部分就是在讨论哪些元素应该被引入 HTML。HTML 应该引入<figure>吗?HTML 应该引入<person>吗?引入<rant>怎么样?我们做出决定,编写规范,作为页面作者,实现 HTML 规范,然后,web 向前发展。

当然,HTML 不可能让所有人都满意。没有任何标准能做到这一点。总会有些想法被卡掉。例如,HTML5 中就没有<person>元素。(还没有<rant>元素,该死的!)虽然没有什么能够阻止你在你的页面中使用<person>元素,但是它是不合法的,不能跨浏览器使用,并且有可能与 HTML 未来版本中新增的元素产生冲突。

好吧,创造自己的标记不是个好办法。那么,web 作者该怎么办呢?有些努力试图扩展 HTML 的早期版本。最流行的是 microformat。它使用 HTML 4 的 class 和 rel 属性。另外一个选择是 RDFa,它原本为了 XHTML 设计,但现在已经被移植到 HTML。

Microformat 和 RDFa 都有它们各自的长处和缺点。它们殊途同归:使用不是 HTML 语言定义的具有额外语义的标签扩展 web 页面。我并不想让本章陷入一场激烈讨论之中(这需要有个 <rant> 标签)。相反,我希望将我们的解决办法引入第三种选择:HTML5 提供的 microdata。

什么是 Microdata?

下面这句话中每一个字都很重要,请注意!

Microdata 使用具有一定作用域的,从自定义词典中获取的键值对,来标注 DOM。

什么意思?我们从后面开始解释。Microdata 核心概念是自定义词典。将“HTML5 所有元素的集合”当做一个词典。这个词典包含了能够表示章节或者文章的元素,但是并没有表示一个人或者一件事的元素。如果你希望表示 web 页面上的一个人,你需要定义自己的词典。Microdata 允许你这么做。每个人都可以定义 microdata 词典,然后在 web 页面中嵌入自定义属性。

第二件关于 microdata 的事情是键值对。每一个 microdata 词典定义一个具有名字的属性的集合。例如,一个 Person 词典定义了 name 和 photo 属性。为向 web 页面引入特定的 microdata 属性,你可以在特定位置提供这个属性的名字。这取决于你在哪里声明属性名。microdata 有一系列关于如何导出属性值的规则(我们将在后文详细解释这个问题)。

同具名属性一起的是 microdata 的“作用域”的概念。考虑 microdata 作用域的最简单方式是想象 DOM 结构中节点的父子关系。<html>元素包含两个子元素:<head><body><body>通常包含多个子元素,每一个子元素都可能再包含自己的子元素。例如,你的页面可能有一个<h1>,包含在<body>元素中的<header>元素中的<hgroup>元素中。数据表格可能有<body>中的<table>中的<tr>中的<td>元素。Microdata 重用了 DOM 的这种层次结构。它提供一种机制,“这个元素的所有属性都是来自于这个词典”。这允许你在一个页面使用多个 microdata 词典。你甚至可以嵌套使用 microdata 词典。这一切都类似于 DOM 的层次结构。(这个问题我们以后会详细讲解。)

现在我们已经谈到 DOM,那么就再深入一些吧。Microdata 可以在你的 web 页面的可视元素上添加额外的语义。Microdata 并不是一个独立的数据格式。它完全是 HTML 的,兼容 HTML。就像你将在下一节中看到的,当你正确使用 HTML 的时候,microdata 可以工作的很好,但是 HTML 词典并不是表现力很强的。Microdata 可以很好地为已经在 DOM 中的数据添加语义。如果你要添加语义的数据不在 DOM 中,你就得重新审视一下 microdata 是不是正确的解决方案。

现在可以很好的理解这句话了吗?“Microdata 使用具有一定作用域的,从自定义词典中获取的键值对,来标注 DOM。”希望是的吧!

Microdata 数据模型

定义自己的 microdata 词典很简单。首先,你需要一个命名空间,它就是一个 URL。命名空间 URL 一般就是这个页面的地址,虽然这一点并不是绝对的。例如,我想创建一个描述人的 microdata 词典。如果我有一个 data-vocabulary.org 域名,那么我就可以使用 URL http://data-vocabulary.org/Person 作为我的 microdata 词典的命名空间。这是一种创建全球范围内的唯一标示符的简单方式:使用你自己域名的 URL。

在这个词典中,我需要定义一些具名属性。让我们定义这么三个基本属性:

  • name(全名)
  • photo(一张你的照片的连接)
  • url(一个你的网站的连接,例如博客或者 Google peofile)

这些属性有些是 URL,另外一些是纯文本。它们都可以通过普通的 web 表单获得,甚至在你考虑 microdata 或词典或其他什么东西之前就可以这么做了。想象一下,你有一个简历页面,或者是一个“关于”页面。你的名字可能作为 heading 标记出来,例如<h1>。你的照片可能使用<img>标签,如果你想让别人看到的话。关于你的简历的任何链接都可以使用超链接标记出来,因为你希望人们点击它们。为了讨论方便,我们假设你的整个简历都是在<section>标记中,从而与页面的其余部分分隔开来。因此我们有:

<section>
    <h1>Mark Pilgrim</h1>
    <p><img src="http://www.example.com/photo.jpg" alt="[me smiling]"></p>
    <p><a href="http://diveintomark.org/">weblog</a></p>
</section>

Microdata 的数据模型是键值对。microdata 属性名(例如本例中的 name 或者 photo 或者 url)通常在 HTML 元素中声明。对应的值则可以从该元素的 DOM 中取得。对于大多数 HTML 元素,属性值通常是元素的内容文本。但有些不是。

Microdata 属性值从何而来?
元素
<meta> content 属性
<audio> src 属性
<embed>
<iframe>
<img>
<source>
<video>
<a> href 属性
<area>
<link>
<object> data 属性
<time> datetime 属性
所有其他元素 文本内容

向你的页面“添加 microdata”意味着要向你正在使用的 HTML 标记添加新的属性。你所要做的第一件事是声明你要使用的 microdata 词典,通过添加itemtype属性。第二件事是声明词典的作用域,通过itemscope属性。在本例中,所有希望增加语义的数据都是在<section>元素中的,所以我们在<section>标记上增加itemtypeitemscope属性。

<section itemscope itemtype="http://data-vocabulary.org/Person">

你的 name 是<section>元素中第一个数据。它包围在一个<h1>元素中。这个<h1>元素没有任何需要特殊处理的 HTML5 microdata 数据模型,所以它就是我们前面的表格中的“所有其他元素”,其 microdata 属性值就从该元素的文本内容中取得。(在你使用<p><div>或者<span>元素显示名字的时候也是类似的。)

<h1 itemprop="name">Mark Pilgrim</h1>

用我们日常语言来说,就是“在 http://data-vocabulary.org/Person 这个词典中有一个 name 属性,其值是 Mark Pilgrim”。

下一步:photo 属性。这个值期望是一个 URL。根据 HTML5 microdata 数据模型,<img>元素的“值”是其 src 属性。我们照片的 URL 已经在 <img src> 属性中了。你所需要做的就是声明<img>元素就是 photo 属性:

<p><img itemprop="photo"
        src="http://www.example.com/photo.jpg"
        alt="[me smiling]"></p>

用我们日常语言来说,就是“在 http://data-vocabulary.org/Person 这个词典中有一个 photo 属性,其值是 http://www.example.com/photo.jpg”。

最后,url 属性也是一个 URL。根据 HTML5 microdata 数据模型,<a>元素的“值”是其href属性。同样,这次我们也能够很好的匹配已有标记。我们所要做的就是在这个<a>元素中声明,这就是url属性:

<a itemprop="url" href="http://diveintomark.org/">dive into mark</a>

用我们日常语言来说,就是“在 http://data-vocabulary.org/Person 这个词典中有一个url属性,其值是 http://diveintomark.org/”。

当然,如果你的标记有些许不同也没有关系。你能够为任何 HTML 标记添加 microdata 属性和值,甚至是像 20th-century-era、tables-for-layout、Oh-God-why-did-I-agree-to-maintain-this 这样的胡扯的标记。不过,我们并不建议使用这种标记,虽然它同其他标记没什么不同,也能够增加 microdata。为了我们亲爱的上帝,不要这么做:

<TABLE>
    <TR><TD>Name<TD>Mark Pilgrim
    <TR><TD>Link<TD>
    <A href=# onclick=goExternalLink()>http://diveintomark.org/</A>
</TABLE>

为了标记name属性,我们需要在包含了名字的单元格上增加itemprop属性。表格单元格对于 microdata 属性值没有特殊规则,因此它还是使用默认值,“文本内容”。

<TR><TD>Name<TD itemprop="name">Mark Pilgrim

增加 url 属性看上去更扯。这个标记没有正常使用<a>元素。它没有吧链接地址放在href属性中,确切的说,href属性没干什么事,它是用的在onclick属性的 Javascript 函数来打开一个外部地址。如果要让我们维护这种代码,不要忘记加上一句“额滴神呐,别这么干了!”然后,我们假定这个函数会打开一个小小的没有滚动条的弹出窗。

不管怎么说,你还是能够将它转换成一个microdata的属性,不过需要有一点点创造性。直接使用<a>标签已经不管用了。链接目标不在href属性中,并且没有办法重写“<a>元素的microdata属性值在href属性中”这个规则。但是你可以为整个代码增加一个外围元素,并且将这个外围元素指定为url属性:

<TABLE itemscope itemtype="http://data-vocabulary.org/Person">
    <TR><TD>Name<TD>Mark Pilgrim
    <TR><TD>Link<TD>
        <span itemprop="url">
            <A href=# onclick=goExternalLink()>http://diveintomark.org/</A>
        </span>
</TABLE>

<span>没有特殊规则,因此使用默认的“microdata 属性是文本内容”。“文本内容”并不是“这个元素中的所有标记”(或许你会说是 innerHTML DOM 属性)。它的含义是“只是文本”。在本例中,就是  http://diveintomark.org/,在<span>元素中的<a>元素的文本。

总结一下:你可以给任何标记增加 microdata 属性。如果你正确地使用 HTML,你会发现,这样会比错误地使用 HTML 标记简单得多。不过,即是错误使用,我们还是有办法解决的。

3 Comments

  1. 美瑞网 2012年2月15日
  2. 美瑞网 2012年2月15日
    • DevBean 2012年2月15日

Leave a Reply