求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Modeler   Code  
会员   
 
  
 
 
     
   
分享到
使HTML5 微数据发挥作用
 

作者:Lin Clark ,发布于2012-7-10

 

目录

第 1 部分: 在微数据之上使用 jQuery

第 2 部分: 利用微数据实现新一代聚合

第 1 部分: 在微数据之上使用 jQuery

简介

像 jQuery 此类的库使开发人员创建站点的方式发生了革命性的变化,促进了大量可方便地添加至 HTML 的实用脚本的开发。微数据具有进一步推进此项革命的潜力,可以更加容易地创建可在任何站点上进行无缝工作的脚本,无论 HTML 模板有何变化。

例如,要在地图上显示计划的事件,jQuery 插件会集成 Google 地图,使在您站点上创建交互式地图变得简单。而您所要做的是以一种结构化格式(比如 JSON 或 CSV)创建一个包含位置的文件。但是,如果您还希望在页面上以 HTML 格式显示信息,拥有这种具有独立的结构化格式的数据可能是个难题。要同时去维护 HTML 和数据文件中的内容,您要么必须编写一段脚本来实现页面上 HTML 和数据文件之间转换,要么您必须重复执行工作。这种方法可能会很快导致 HTML 和数据文件不同步。

保持文件同步是使用像微数据和 RDFa 等 HTML 数据格式的一项重要优势,您可以像平常一样编写 HTML,然后在 HTML 标记中添加一些属性,使它和您的数据存储大小翻倍。因为这些 HTML 数据格式都是由 WHARWG 和 W3C 开发和批准的,人们已经构建了如何从 HTML 提取数据的构建工具,并且您可以在您的站点上轻松重用这些工具。

由于微数据只最近才开始受到人们的关注,所有只有少量已发布的插件提供了支持。有一个 jQuery UI Map 插件示例,它提供了上面所描述的地图。

创建一个预配 Rich Snippet 的事件地图

您可以使用一小段的 HTML 以同时获得交互式事件地图和较出色的 SEO。

正如之前一篇文章(参见 参考资料 获得链接)所介绍的,微数据可与 Schema.org 词汇表中的术语结合使用,以帮助搜索引擎更好地理解您的内容。此方法使搜索引擎能够显示 Rich Snippet,后者可在搜索结果自身中显示关于页面的最重要信息。

为获得 Rich Snippet 而添加的注释可执行双重任务。除了能够更好地搜索结果,还可以将它使用在您自己的页面上实现更出色的显示。

您将使用一个 jQuery 插件完成此项任务。我在示例代码 下载 中提供了相关的文件,其中包含该插件略加修改的版本。

基本的事件清单

让我们创建一个全球的 DrupalCamp 事件清单。首先,创建一个包含两个事件的 HTML 页面,如 清单 1 中所示。

清单 1. 列出两个事件的基本 HTML

<!DOCTYPE html>
  <head>
    <title>Upcoming DrupalCamps</title>
  </head>
  <body id="doc">
    <h1>Upcoming DrupalCamps</h1>

    <!-- Event 1: DrupalCamp Toulouse -->
    <div>
      <h2><a href="http://example.com/drupalcamp_fr">DrupalCamp Toulouse 2011</a></h2>
      <img src='images/drupalicon_fr.png' />
       p>Vous l’attendiez tous, le DrupalCamp Toulouse aura bien lieu, 
réuni avec 2 autres événements sous la bannière 
"Capitole du Libre": le DrupalCamp, une Ubuntu Party, une Akademy 
(évènement KDE).</p>
      <div>
        ENSEEIHT, Toulouse, Haute-Garonne, FR
      </div>
      <div>
        <time datetime="2011-11-26T09:00:00+01:00">November 26, 10:00am</time> –
        <time datetime="2011-11-27T17:00:00+01:00">November 27, 6:00pm</time>
      </div>
    </div>

    <!-- Event 2: DrupalCamp Ohio -->
    <div>
      <h2><a href="http://example.com/drupalcampohio">Drupalcamp Ohio 2011</a></h2>
      <img src='images/drupalicon_oh.png' />
      <p>The Central Ohio Drupal User Group (CODUG) is proud to announce 
Ohio’s first Drupalcamp. On Saturday, December 3rd, we’ll hold an 
all-day camp with keynote speaker, breakout sessions and Birds of Feather groups at The 
Ohio State University’s Nationwide and Ohio Farm Bureau 4-H Center.</p>
      <div>
        The Ohio State University, Columbus, Ohio, US
      </div>
      <div>
        <time datetime="2011-12-03T09:00:00-05:00">December 3, 9:00am</time> –
        <time datetime="2011-12-03T17:00:00-05:00">5:00pm</time>
      </div>
    </div>

  </body>
</html>

请注意,您使用一个特殊元素标记了日期。此元素是新时间元素,该元素是核心 HTML5 标准的一部分。它能够向页面添加准确时间,所以可由应用程序轻松地解析和应用。在此示例中,Google 使用这些时间元素从页面中选择另外 3 个事件以便在 Rich Snippet 中显示。请注意,在发布时,关于是否将时间元素更改为一种更加通用的数据元素的问题存在着争议。如果这一提议得以通过,“time” 将替换为 “data”,“datetime” 将替换为下面代码中的 “value”。

datetime 是以 YYYY-MM-DD 格式开始的。接下来,一个 “T” 将日期与时间分开,时间格式显示为 HH:MM:SS。然后提供相对于世界标准时间 (UTC) 的偏移。例如,冬天的法国,时间要比 UTC 提早一小时,所以要在 datetime 字符串末尾加上 ‘+01:00’ 的偏移量。冬天的 Ohio 要比 UTC 晚 5 小时,所以要在 datetime 字符串末尾添加 ‘-05:00’ 的偏移量。这种添加会使中部标准时间 2011 年 12 月 3 日上午 9 点得到机器可读的值 “2011-12-03T09:00:00-05:00”。

将文件保存到 Web 服务器中的 jquery-ui-map/demos 目录并将它加载到您的浏览器中。图 1 显示 清单 1 中描述的两个事件的详细信息。

图 1. 列出两个事件的基本页面

实现事件的 Rich Snippet

具有时间元素的页面包含少量机器可理解的信息。现在看看,如果这一添加发生更改,Google 会如何显示结果。转到 Google 的 Rich Snippets Testing Tool,输入您页面的 URL(参见 图 2)。您看到的不是事件详细信息,而是预览生成错误信息,上面显示着页面没有作者标记、Rich Snippet 标记或作者信息的。

图 2. Rich Snippets Testing Tool 中没有基本 HTML 的结果

即使 Google 知道您的页面列出了时间,但它也不知道这些时间是事件的开始和结束时间。要帮助 Google 理解这一点,您需要添加一些 Schema.org 术语(参见 清单 2)。关于使用微数据发布 Schema.org 标记已在之前的一篇文章有更详细地介绍(请参见 参考资料 获取链接)。

清单 2. 将每个事件的 <div> 添加到一个 Event 项中

var audioElement = <!-- Event 1: DrupalCamp Toulouse -->
<div itemscope itemtype="http://schema.org/Event">
  ...
</div>

<!-- Event 2: DrupalCamp Ohio -->
<div itemscope itemtype="http://schema.org/Event">
  ...
</div>

接下来将 url 和 name 属性添加到事件中。请注意,在名称两边添加一个 <span>,以留出空间来添加 itemprop 属性。您还要添加 image 属性。虽然在 Rich Snippet 中无需用到该 image,但在稍后就会用到它。

清单 3. 向事件添加 url 和 name 属性

<!-- Event 1: DrupalCamp Toulouse -->
<div itemscope itemtype="http://schema.org/Event">
  <h2><a href="http://example.com/drupalcamp_fr" itemprop="url"><span 
itemprop="name">DrupalCamp Toulouse 2011
  <img itemprop="image" src='images/drupalicon_fr.png' />
  ...
</div>

<!-- Event 2: DrupalCamp Ohio -->
<div itemscope itemtype="http://schema.org/Event">
  <h2><a href="http://example.com/drupalcampohio" itemprop="url"><span 
itemprop="name">Drupalcamp Ohio 2011</span></a></h2>
  <img itemprop="image" src='images/drupalicon_oh.png' />
  ...
</div> 

现在您可以添加一个开始时间(可选项)和一个结束时间。因为您使用了时间元素,所以您已经拥有开始时间和结束时间的机器可读值。您只需添加 Schema.org 术语来让 Google 知道各种值的对应关系(参见 清单 4)。

清单 4. 在时间元素上添加 startDate 和 endDate 属性

<!-- Event 1: DrupalCamp Toulouse -->
<div itemscope itemtype="http://schema.org/Event">
  ...
  <div>
    <time itemprop="startDate" datetime="2011-11-26T09:00:00+01:00">November 26, 
10:00am</time> –
    <time itemprop="endDate" datetime="2011-11-27T17:00:00+01:00">November 27, 
6:00pm</time>
  </div>
</div>

<!-- Event 2: DrupalCamp Ohio -->
<div itemscope itemtype="http://schema.org/Event">
  ...
  <div>
    <time itemprop="startDate" datetime="2011-12-03T09:00:00-05:00">December 3, 
9:00am</time> –
    <time itemprop="endDate" 
datetime="2011-12-03T17:00:00-05:00">5:00pm</time>
  </div>
</div> 

再次在 Testing Tool 中测试该页面。因为 URL 指向一个与基本 URL 不同的域,您会看到阻止 Rich Snippet 显示的警告(参见 图 3)。

图 3. 阻止 Rich Snippet 显示的警告

Google 要求事件的链接指向相同域中的页面。这一要求旨在预防垃圾信息。如果您搜索 example.com 并将其替换为您的域,然后再次进行测试,您应该会看到 Rich Snippet 的显示,如 图 4 所示。

图 4. 同时显示了两个事件及其开始日期的 Rich Snippet

请注意,即使测试工具向您显示了一个 Rich Snippet,您也无法保证在真实的搜索结果中会显示 Rich Snippet。您必须向 Google 申请检查您的站点,Google 才会在搜索结果中启用您页面的 Rich Snippet 输出。更多相关信息请查看常见问题解答。

添加 jQuery UI 地图

因为 DrupalCamps 在全球各地举办,所以您的访问者希望有个地图来显示合理旅行范围内所发生的事件。要获得地图,只需添加另外一些信息。

首先,设置地图的显示。在文档中添加一个 <div> 以将地图放置在页面标题下和事件清单上(参见 清单 5)。

清单 5. 添加地图 <div>

<body id="doc">
  <h1>Upcoming DrupalCamps</h1>

  <div>
    <div id="map_canvas"></div>
  </div>

 <!-- Event 1: DrupalCamp Toulouse -->  

您需要添加一些 JavaScript 文件来将此 <div> 转换为一种交互式地图。另外还要添加一些 CSS 文件,为 #map_canvas <div> 提供一个高度,使您可以看到它。本地文件包含在源代码中(参见 下载)。

清单 6. 添加外部 CSS、JavaScript 库和内联 jQuery

<head>
  <title>Upcoming DrupalCamps</title>

  <!-- External Stylesheets -->
  <link rel="stylesheet" type="text/css" 
href="http://yui.yahooapis.com/3.2.0/build/cssreset/reset-min.css" />
  <link rel="stylesheet" type="text/css" 
href="http://yui.yahooapis.com/3.2.0/build/cssbase/base-min.css" />
  <link rel="stylesheet" type="text/css" 
href="http://yui.yahooapis.com/3.2.0/build/cssfonts/fonts-min.css" />
  <link rel="stylesheet" type="text/css" href="css/main.css" />

  <!-- Google Maps API and jQuery, served by Google -->
  <script type="text/javascript" 
src="http://maps.google.com/maps/api/js?sensor=false"></script>
  <script type="text/javascript" 
src="http://ajax.googleapis.com/ajax/libs/jquery/1.6/jquery.min.js"></script>
  <!-- jQuery UI Maps files for placing markers and for parsing Microdata -->
  <script type="text/javascript" src="../web/jquery.fn.gmap.js"></script>
  <script type="text/javascript" 
src="../ui/jquery.ui.map.services.js"></script>
  <script type="text/javascript" 
src="../ui/jquery.ui.map.microdata.js"></script>
  ...   

然后添加一个 jQuery 代码块,它会在页面初始化时获取 #map_canvas div 并将其转换为一个地图(参见 清单 7)。稍后将更详细地介绍此功能。

清单 7. 初始化地图

...
  <!-- Grab the #map_canvas div and turn it into a map -->
  <script type="text/javascript">
    $(function() {
      map = $('#map_canvas');

      map.gmap().bind('init', function () {
      });
    });
  </script>
</head>  

重新加载页面时,您将会看到地图(如 图 5 所示)。它还未标记任何事件,您还需要添加更多信息来显示这些事件。

图 5. 没有任何标记的基本地图

在微数据中添加位置

在将标记添加到地图之前,您需要在微数据中添加事件的位置。暂时先将每个地址视为单个字符串。但是,地址包含多个不同的部分,并且您希望在微数据中表达此结构,即使以后对 HTML 结构进行更改也能轻松一致地获得正确的值。

首先,添加 location 属性,它会为它的值获得一个 Place(参见 清单 8)。

清单 8. 向事件添加 location 属性

<!-- Event 1: DrupalCamp Toulouse -->
<div itemscope itemtype="http://schema.org/Event">
  ...
  <div itemprop="location" itemscope itemtype="http://schema.org/Place">
    ENSEEIHT, Toulouse, Haute-Garonne, FR
  </div>
  ...
</div>  

Place 可以拥有一个姓名和一个通信地址。通信地址拥有自身的属性项,其中包括街道地址、城市 (addressLocality)、州 (addressRegion) 和 addressCountry (应该是一个二位字母代码 ISO 3166-1 alpha-2)。清单 9 使用 span 标记将这些属性隔开。

清单 9. 使用 span 标记

<!-- Event 1: DrupalCamp Toulouse -->
<div itemscope itemtype="http://schema.org/Event">
  ...
  <div itemprop="location" itemscope itemtype="http://schema.org/Place">
    <span itemprop="name">ENSEEIHT</span><br /> 
    <span itemprop="address" itemscope itemtype="http://schema.org/PostalAddress">
      <span itemprop="streetAddress">Rue Sylvain Dauriac</span><br />
      <span itemprop="addressLocality">Toulouse</span>,
      <span itemprop="addressRegion">Haute-Garonne</span>,
      <span itemprop="addressCountry">FR</span>
    </span>
  </div>
  ...
</div> 

您可采用相同方式格式化其它事件的地址。

在地图上放置位置

您已准备好向地图中添加标记。首先,将页面上的微数据解析为一个可以使用的对象。为此,指定哪种类型的顶级项是您想要的数据来源。微数据中的顶级项可视为根项;这些项不是任何其它项的属性,而是拥有自己的属性。指定 http://schema.org/Event。这会为每个事件返回一个对象(参见 清单 10)。

清单 10. 将微数据解析为对象

<script type="text/javascript">
    $(function() {
      map = $('#map_canvas');

      map.gmap().bind('init', function () {
        // Process the microdata for each Event into an object.
        map.gmap('microdata', 'http://schema.org/Event', function(result, item, index) {
          window.console.log(result);
        });
      });
    });
</script> 

您可以在 Firefox 和 Chrome 等浏览器中看到在 JavaScript 控制台中由微数据创建的对象。微数据中的每项被转换成一个具有自己的属性对象的对象,其中包含来自该项的所有 itemprop 值。因为微数据中的属性可能具有多个值,所以将 itemprop 值当作数组来处理(参见 图 6)。

图 6. 在 Chrome JavaScript 控制台中检查对象

这个对象拥有您获得位置的地理坐标所需的所有属性,您需要在事件上放置该位置的标记。要获得此信息,从对象中提取地址的各部分并将它们组合成一个 Google 能读取的地址字符串。您然后可使用 Google 的 Geocoder 获得此地址的坐标。jQuery UI Map 库提供了一个包装器函数,您可以使用它运行 Geocoder 请求。

请注意,如果您获得了一个未定义的错误,请仔细检查以确保您在所列出的所有事件上拥有所有需要的属性(参见 清单 11)。

清单 11. 运行地址的 Geocoder 请求

<script type="text/javascript">
    $(function() {
      map = $('#map_canvas');

      map.gmap().bind('init', function () {
        // Process the Microdata for each Event into an object.
        map.gmap('microdata', 'http://schema.org/Event', function(result, item, index) {
          // Traverse from the Event to the Place and from the Place to the
          // Address to get the properties.
          var placeName = result.properties.location[0].properties.name[0];
          var streetAddress = 
result.properties.location[0].properties.address[0].properties.streetAddress[0];
          var city = 
result.properties.location[0].properties.address[0].properties.addressLocality[0];
          var state = 
result.properties.location[0].properties.address[0].properties.addressRegion[0];
          var country = 
result.properties.location[0].properties.address[0].properties.addressCountry[0];

          // Join the address parts into a comma-separated string.
          var address = [placeName, city, state, country].join(', ')

          // Run the Geocoder request for the address.
          map.gmap('search', {'address': address } , function(result, status) {
            window.console.log(result);
            // We will place the marker here.
          });
        });
      });
    });
</script>  

如果在控制台中查看结果,您将看到该服务返回了一个或多个与您的地址匹配的位置。您将近使用第一个位置,因为这是最佳的匹配值。该对象有一个 geometry 属性,其中包含您需要的地理坐标信息(参见 清单 12)。

清单 12. 放置标记

<script type="text/javascript">
    $(function() {
      map = $('#map_canvas');
      map.gmap().bind('init', function () {
        // Process the Microdata for each Event into an object.
        map.gmap('microdata', 'http://schema.org/Event', function(result, item, index) {
          // Traverse from the Event to the Place and from the Place to the
          // Address to get the properties.
          var placeName = result.properties.location[0].properties.name[0];
          var streetAddress =
result.properties.location[0].properties.address[0].properties.streetAddress[0];
          var city = 
result.properties.location[0].properties.address[0].properties.addressLocality[0];
          var state = 
result.properties.location[0].properties.address[0].properties.addressRegion[0];
          var country = 
result.properties.location[0].properties.address[0].properties.addressCountry[0];

          // Join the address parts into a comma-separated string.
          var address = [placeName, city, state, country].join(', ')

          // Run the Geocoder request for the address.
          map.gmap('search', {'address': address } , function(result, status) {
            if (status == google.maps.GeocoderStatus.OK) {
              // Create a LatLng object.
              var lat = result[0].geometry.location.lat();
              var lng = result[0].geometry.location.lng();
              var latlng = new google.maps.LatLng(lat, lng);
  
              // Place the marker.
              var markerOptions = { 
                'bounds':true,
                'position': latlng
              };
              map.gmap('addMarker', markerOptions);
            } else {
              alert("Geocode was not successful for the following reason: " + status);
            }
          });
        });
      });
    });
</script> 

当重新加载页面时,您应该看到如 图 7 中所示的位置标记。

图 7. 放置在地图上的标记

实现交互式地图

如果用户可单击标记来获得事件详细信息,比如事件的日期和链接,地图会变得更有用。添加此功能并不难。

首先,从解析的微数据中提取您想要的关于该事件的附加信息(参见 清单 13)。

清单 13. 获得补充信息

<script type="text/javascript">
    $(function() {
      map = $('#map_canvas');
      map.gmap().bind('init', function () {
        // Process the Microdata for each Event into an object.
        map.gmap('microdata', 'http://schema.org/Event', function(result, item, index) {
          var eventName = result.properties.name[0];
          var logo = result.properties.image[0];
          var url = result.properties.url[0];
          var start = result.properties.startDate[0];

          ...
      });
    });
</script> 

在您将标记添加到地图之前,创建一个包含事件详细信息的 HTML 代码块(参见 清单 14)。

清单 14. 创建信息窗口的 HTML

            // Run the Geocoder request for the address.
            map.gmap('search', {'address': address } , function(result, status) {
              if (status == google.maps.GeocoderStatus.OK) {
                // Create a LatLng object.
                var lat = result[0].geometry.location.lat();
                var lng = result[0].geometry.location.lng();
                var latlng = new google.maps.LatLng(lat, lng);
    
                var eventDetails = '';
                eventDetails += '<div class="iw">';
                eventDetails += '<img src="'+logo+'"></img>';
                eventDetails += '<h2><a href="'+url+'">'+eventName+'</a></h2>';
                eventDetails += new Date(start).toDateString();
                eventDetails += '</div>';
    
                // Place the marker.
                ...  

然后将事件详细信息添加到您创建的标记。使用 jQuery 的 .click 来表明您希望在某人单击该标记时运行哪个函数。在该函数中,使用 jQuery UI Maps 库提供的 openInfoWindow 帮助器函数来构建窗口,并传入您的 HTML 作为该窗口的内容(参见 清单 15)。

清单 15. 添加 Info Window 作为单击事件

            // Place the marker.
            ...
            map.gmap('addMarker', markerOptions).click( function() {
              map.gmap('openInfoWindow', { 'content': eventDetails }, this ); 
            });   

完成此任务后重新加载,然后单击该标记。您将看到弹出了一个包含事件详细信息的窗口(参见 图 8)。

图 8. 单击事件标记

要改善外观,添加一些 CSS 规则。我在可下载的示例代码中添加了这些规则(参见 下载)。最后,您的地图类似于 图 9。

图 9. 最终的地图

结束语

微数据通过利用 jQuery 插件使您可以轻松地以动态方式在您页面上使用数据,比如在 Google 地图上。微数据规范探讨了通用脚本,该脚本可用在不同和不相关站点上作为插件。微数据还使通过组合来自多个不同站点的数据来创建新应用程序的过程变得简单。在下一篇文章中,我将演示如何使用 Drupal 创建这样一个应用程序。

第 2 部分: 利用微数据实现新一代聚合

简介

大型组织往往会投资开发那些大型的、集中的、标准化的 IT 系统,例如整体 CMS,然后竭尽所能让所有人都能够使用这样的系统。遗憾的是,保证所有人按照正确的方式使用系统是一项艰巨的挑战。投资开发一刀切的方法很难交付承诺的生产力收益。标准化或者控制松散耦合的组织尤为艰难,因为这种组织中的团队很少交互,往往分别制定决策。松散耦合的组织示例包括:

  • 大学中的各院系
  • 开源社区中的企业和个人
  • 业余体育联赛中的队伍

在本系列的 使 HTML5 微数据发挥作用,第 1 部分:在微数据之上使用 jQuery 中,我们学习了如何在微数据的基础之上使用通用脚本。我们编写了一个 HTML 片段,提供交互式事件地图,并使 Google、Bing 和 Yahoo 能够使用 Rich Snippet 在搜索结果中更好地显示您的页面。

在本文中,您将学习如何利用微数据,支持协作小组轻松将其站点挂接到一个集中的小组站点上,并共享内容。通过商定在 HTML 标记中设置的一组属性,松散耦合的组织便可维护其信息系统的独立性,同时仍然能够构建联合项目。

场景:为 Drupal 创建一个分散的文档系统

许多开放源码项目都难以为其软件维护健壮的、最新的文档。与此同时,项目的贡献者利用博客文章分享具体的技术说明,这些博客文章往往在 Planet 中聚合。Planet 就是一种博客聚合器,能够获取选定作者的博客文章(请参见 参考资料 部分)。

Planet 是参与社区最新活动和讨论的有效方法,但无法发挥作为协作技术的潜力。它难以筛选 Planet 文章的存档,因为其中包含大量原始结构化数据。即使聚合文章确实包含有用的结构化数据(如标签),来自不同站点的文章往往也不会共享相同的术语,它们或许会使用术语的不同拼写方法。因此,无法有效地对文章进行排序。

通过创建获取博客文章及有关文章的额外重要信息的聚合器,可以解决这样的问题。可以使用聚合器来浏览文章,并将其放置在项目主站点内的相关位置。

假想的系统将归档 Drupal。我们的博客文章中充分说明了某些广泛应用的子系统(在 Drupal 中称为模块),但 Drupal.org 手册中缺少良好的文档。我们的目标在于将 Planet 中的出色文档转入 Drupal.org 便捷的可搜索结构之中。

规划系统

第一项任务是确定希望将博客文章中的哪些信息传递到中心归档系统。例如,您希望指明该文章讨论的是哪些模块。通常情况下,模块的各主要版本往往会采用不同的工作方式,因此最好指明教程是否与特定的模块版本相关。

Drupal 中有多种角色,从内容编辑到后台开发。指明哪些角色认为文章有帮助是非常有价值的。图 1 中的文档记录显示了标题、读者和相关模块。

图 1. 示例文档记录

该场景中的数据共享需求非常简单。您仅需将源博客文章中的以下信息传递到站点即可:

  • 标题
  • 摘要段落
  • URL
  • 目标读者
  • 模块

标题、摘要和 URL 已经通过 RSS 实现了结构化的格式。您需要找到一种解决方案,获取有关目标读者和模块的结构化数据。为此,可以使用微数据。开始使用微数据之前,您需要设置测试使用的源和目标站点。

源站点

为了解析和处理传入的文章,您需要使用 Microdata Import 模块。该模块接收一个源 URL,因此源必须能够输出 RSS 或者 Atom。

可以使用 Drupal 这样的 CMS,其中包含的工具能够自动化放置微数据,您也可以选择使用另外一个博客系统(只要该系统不会删除微数据属性即可)。对于 Microdata Import 模块,所导入的每个项目都必须与一个源项相关联,保证每份教程都使用自己的页面。

该场景使用托管的博客平台 Blogger 和 Drupal Gardens。您可以设置自己的源,或者使用以下源:

http://mdsource1.blogspot.com/feeds/posts/default

http://mdsource2.drupalgardens.com/blog/feed

所有必要的信息均直接处于 HTML 标记之中,因此您可以为源使用任何工具。HTML 中的微数据作为标准、只读的 API,与生成它的后台代码无关。

设置目标站点

有了用于测试的源之后,即可开始设置聚合站点。首先是基本设置:

安装 Drupal 7 并下载以下模块:

  • Microdata Import
  • Feeds
  • Ctools
  • Job Scheduler
  • Libraries
  • HTTP Client

启用 Microdata Import 和 Feeds 管理 UI。您将看到提示,要求您启用另外四个依赖项。将 MicrodataPHP 库下载为 sites/all/libraries/MicrodataPHP/MicrodataPhp.php。该库获取一个 HTML 页面,并提取微数据。

配置在获取源时需要使用的导入设置:

转到 Structure -> Content types,创建两种内容类型:一个用于管理源,另一个用于保存教程本身。您可以分别将它们称之为

Tutorial import 和 Tutorial。将所有设置保留默认值。

转到 Structure -> Feeds importers,添加一个导入器。

单击 Basic Settings 部分左栏中的 Settings。在 Attach to content type 下拉菜单中,选择您刚刚创建的内容类型,并保存它。图 2 中选择了 Tutorial import。

图 2. 配置源导入器的基本设置

单击解析器旁边的 Change。切换到 Microdata Import Parser(从 RSS/Atom),并单击 Save。

屏幕顶端将显示一条确认信息 “Changed parser plugin”。

在 Processor 下方,单击 Settings。将 Update 设置更改为 Update existing nodes,如 图 3 所示,选择 Tutorial 更改内容类型。

将文本格式更改为 Filtered HTML。由于您正从不一定信任的站点中导入内容,因此不应使用 Full HTML。否则将导致您的站点易受跨站点脚本攻击。

图 3. 配置处理一个节点内的源项的设置

在 Processor 下方,单击 Mapping。在这里可以定义要将源文章的哪些部分添加到目标节点,以及将其添加到的位置。由于您尚未添加有关可用微数据内容的信息,因此这里仅列出了 RSS/Atom 中公开的元素。

在 URL 之间建立映射,单击 Add。选中 Unique Target 复选框,单击 Save。这能确保在后续运行中您可以对项进行匹配,并将源中的任何更改复制到目标。

在标题之间建立映射,单击 Add。

将描述映射到正文,并单击 Add,如 图 4 所示。

图 4. 从源映射到目标

为了进行测试,您可以导入相关内容:

  1. 单击 Add content,添加一个新的 Tutorial import。
  2. 将其标题设置为 Source 1。
  3. 在 Feed URL 字段中,添加源并单击 Save。
  4. 选择 Import 选项卡,单击 Import。此时应该看到一条表示已经创建了一个或者多个节点的消息,如 图 5 所示。

图 5. 从源中导入的节点

转到主页,查看已经导入的文章。由于已经导入了完整的文章,因此您可能无法清除地认识到下面要做些什么。但由于您并未保留原始文章结构,因此现在还无法根据目标读者或者模块筛选文章。此时就会用到微数据。

图 6. 已经导入的一个节点

标记源内容以便使用它们

既然已经能够正确获取源,下面就可以开始将微数据添加到标记中,并通过文章引入微数据。清单 1 展示了一篇博客文章的基本标记。清单 1. 一篇文章的基本 HTML 标记

<h2>Building modules on top of SPARQL Views</h2>
<div>

 <p>This video demonstrates how you can build a module that installs a 
 View powered by a SPARQL query whenever it is enabled.</p>
  <b>Audience:</b> Developer <br />
  <b>Modules:</b>
  <ul>
    <li>Views</li>
    <li>SPARQL Views</li>
  </ul>
</div> 

您需要指明该内容属于文章。该场景使用 Schema.org 词汇表标记文章,因为 Schema.org 中包含需要注释的大多数内容所需的术语(请参见 参考资料 部分)。只有在所有协作作者都同意的情况下,才应使用其他词汇表。[在 “结合使用 Drupal、HTML5 和微数据”(请参见 参考资料 部分)中,我更加深入地探讨了如何放置微数据。本文中介绍了如何手动添加微数据,如何利用 Microdata 模块自动化此过程。]

您需要从 RSS 源中获取标题,因此不必为标题使用标记。但标记标题能使其他用户更轻松地重用数据。您可以使用 name 属性,如 清单 2 所示。由于标题位于文章的 div 以外,因此您必须在 div 中添加一个 meta 元素来提供标题。对摘要段落使用 description 属性,这将提供比 RSS 描述更加具体的访问。

清单 2. 为文章添加基本的微数据

<h2>Building modules on top of SPARQL Views</h2>
<div itemscope="" itemtype="http://schema.org/Article">

  <meta itemprop="name" content="Building modules on top of SPARQL Views" />

    <p itemprop="description">This video demonstrates how you can build a module 
       that installs a View powered by a SPARQL query whenever it is enabled.</p>
    ...
</div>  

更新描述

上面,我们已经使用微数据进行了标记,下面即可仅获取文本中的描述。这将从描述中排除目标读者和相关模块,这种做法非常好,稍后即可将这些信息纳入其自己的字段。将映射更改为使用微数据描述,而非 RSS 描述。

转到 Structure -> Feeds importers,编辑您的导入器。

在 Parser 下方,单击 Settings。在字段中输入一个示例源页面,如 图 7 所示。

示例页面将获得解析,您可以看到哪些属性可用,因此示例应该尽可能地保持完整。保存设置

图 7. 使用示例页面提供属性路径

在 Processor 下方,单击 Mapping。在 Description 行中,选择 Remove,再单击 Save。这将删除 RSS 描述与正文字段之间的樱红色。

单击 Select a source 下拉菜单项。列表中现在包含了新的源元素,这些元素是通过示例源确定的。

选择新的描述元素(列表中的第二个描述元素),将其映射到正文,并单击 Add,如 图 8 所示。

图 8. 更新描述映射

找到您的 Source 1 Tutorial import,单击 Import 选项卡。单击 Import 按钮,节点将更新。Audience 和 Module 文本不再并入描述部分,如 图 9 所示。

图 9. 更新后的节点使用微数据描述而非 RSS 描述

更新不仅会删除描述中您不需要的内容。还会对全部导入信息执行完整更新。如果对源文章的措辞做出了修改,新的措辞也会显示在这里。将更新功能配置为 Cron 定期运行,因此无需手动触发即可获得定期更新。这里可以看到 Feeds 系统的强大力量。它能实现打造有效的协作站点网络所必不可少的轻松而自动化的同步。

添加目标读者角色

至此,您已经标记了所有文章共有的一些信息片段:标题和描述。在这一节中,您将转到场景特有的信息。此时有必要与协作团队配合工作,了解他们如何看待他们所提供的内容。信息应该反映协作人员的心理模式(而非遵照外部的理想做法)。

Drupal 社区已经定义了一组成熟的角色,表示为会议中的分工轨迹。Drupal Skill Map 项目将这些角色定义为:

  • 系统架构师
  • 开发人员
  • 主题设计人员
  • 站点构建人员
  • 内容编辑人员
  • 设计/UX
  • 项目经理
  • Drupal 市场营销人员

您需要按照上述八个分组来表示文章的目标读者。遗憾的是,Schema.org 词汇表并没有目标读者的概念,因此您在处理 itemprop 时有两种选择:

使用 Schema.org 归档的扩展机制对其进行扩展,即选择一种现有属性,并在末尾处添加 /audience。

例如,您可以将 keywords 属性扩展为 keywords/audience,如下所示。

Audience: <span itemprop="keywords/audience">Developer</span>

使用另一个词汇表中的术语,或者创建您自己的词汇表。

例如,如果 Tutorial 词汇表中包含一个目标读者属性(如果您要使用字符串作为该属性的值),那么就可以使用这个替代属性。由于使用了 http://schema.org/Article itemtype,因此您必须引用 Tutorial 词汇表属性的完整 URL,不能使用短属性名称。完整 URL 应该类似于 http://tutorial-vocabulary.org/audience。词汇表文档中应该指定准确的 URL。URL 应放置在 itemprop 属性中,如下所示

Audience: <span itemprop="http://tutorial-vocabulary.org/audience">Developer</span>

对于这个场景,我们将采用第一个选择,扩展 Schema.org。如果您正在手动放置微数据,请将 清单 3 复制粘贴到正文中。如果您正在使用 Drupal 自动在源站点中放置微数据,您可以在文章中创建一个 List (text) 字段,此时文章中将显示复选框,允许选择目标读者。通过在字段设置中添加 keywords/audience 属性,即可自动输出正确的微数据。

使用目标读者角色

为将目标读者元素纳入使用站点的内容中,您需要为其创建一个内容类型字段,随后为该字段创建映射。

转到 Structure -> Content types,为 Tutorial 内容类型单击 Manage fields。

添加目标读者文本字段。

转到 Structure -> Feeds importers,编辑您的导入器。

在 Processor 下方,单击 Mapping。

将 keywords/audience 元素映射到新的 Audience 字段,单击 Add,如 图 10 所示。

图 10. 为映射添加 keywords/audience 属性

再次找到您的 Source 1 Tutorial import,单击 Import 选项卡。转到更新后的教程页面,此时您应看到 Audience 字段已经填充,如 图 11 所示。

图 11. 包含目标读者的更新后节点(完整节点视图)

添加相关模块

可以证明,使用字符串足以按照文章的目标读者对文章进行分类。目标读者角色数量有限,而且不会频繁发生变化。如果出现变化,比如添加新角色,要求人们更新期目标读者字段设置并不是很困难。

但按照相关模块分类则截然不同。Drupal 拥有 14,000 个模块,大多数都有多个版本。至少这意味着 14,000 个不同的标签。标签的格式也是丰富多变的。此外,数以千计的模块维护者可能会随时更改其模块的名称。

为了引用模块,必须使用比字符串更加稳定的一些信息。一种不会经常发生变化的标识符就是 Drupal.org 中的模块 URL(例如,Views 模块的 http://drupal.org/project/views)。可以使用它作为模块的一致标识符。

要添加模块的版本,您应添加模块项的一个属性。然而,对于这个场景,为各版本使用不同的 ID 更加容易。例如,要标识 Views 7.x-3.x,可以使用 URL http://drupal.org/project/views/7/3。尽管该 URL 目前并未显示页面,但是可想而知,该位置的页面将显示 Views 7.x-3.x 的所有教程,并提供该版本的下载。

要为该值使用字符串而非 ID,可以使用微数据的 itemid 属性。itemid 与 itemscope 和 itemtype 属性位于相同的标签中。对 itemtype 使用特定于 Google 的 Schema.org 术语 http://schema.org/SoftwareApplication。使用 about 属性表明该文章与该模块有关。

可见的内容将仍然是名称字符串。您不会用到它,但应该尽可能简化它,以便其他用户能够更容易地使用您的数据。将其公开为模块的 name 属性,如 清单 3 所示。

清单 3. 为相关模块添加微数据

<p>Modules:
  <ul>
    <li itemprop="about" itemscope="" 
        itemtype="http://schema.org/SoftwareApplication" 
        itemid="http://drupal.org/project/views/7/3">
      <span itemprop="name">Views</span>
    </li>
    <li itemprop="about" itemscope="" 
        itemtype="http://schema.org/SoftwareApplication" 
        itemid="http://drupal.org/project/sparql_views/7/2">
      <span itemprop="name">SPARQL Views</span>
    </li>
  </ul>
</p> 

手动添加所有这些数据并不容易。如果有可能,您需要使用能提供帮助的工具。如果对源使用 Drupal,则可以使用 Web Taxonomy 模块,帮助内容作者标记其文章。利用 Web Taxonomy,Web 上的某种分类法将提供自动完成结果。选择术语时,应该将其导入您的站点。这意味着您必须访问 Drupal 项目词汇表中数以万计的术语,而不要将其存储在您的数据库中。添加新标签、更改标记时,自动完成字段有权访问这些数据,您甚至不必去考虑它们。

您还可以使用 Web Taxonomy 来使用相关模块,因此需要在目标站点上进行相应的配置。

为相关模块配置 Web Taxonomy

下载并启用 Web Taxonomy。要配置 Web Taxonomy,您还需要使用一个模块来定义要使用哪种外部分类法,以及如何访问它。Drupal Full 项目的模块可以在 http://drupal.org/sandbox/linclark/1363774 中获得。启用该模块时,一个新的 Drupal Full 项目词汇表将添加到您的站点中。

在目标和源站点中对 Web Taxonomy 进行相同的配置:

转到 Structure -> Content types,管理 Tutorial 内容类型的字段。
添加 Related Modules 字段,如 图 12 所示。选择 Taxonomy Term Reference 字段类型以及 Web Taxonomy autocomplete widget。

图 12. 添加 Web Taxonomy 字段

选择 Drupal Full Projects 词汇表,并 Save 字段设置。

将值的数量更改为 Unlimited,并 Save 设置。

现在,您可以编辑教程并键入模块名称,测试字段。自动完成字段会提供建议,如 图 13 所示。如果选择其中的一项建议并保存教程,那么在查看该教程时就可以看到该标签。如果单击浏览术语页面,您为 ID 使用的 URL 会显示在该术语中。

图 13. Drupal Full 项目的 Web Taxonomy 自动完成

如果您正在为源中的字段配置字段,请下载并启用提供的 Token 模块,更改指派给该术语的 itemid。转到 Structure -> Taxonomy,编辑 Drupal Full 项目词汇表。该字段中提供了由 itemid 使用的标志,将其值更改为 [term:web_tid]。此时将使用全局 Web 术语 ID,而非本地路径。

使用相关模块

至此,您已经得到并测试了 Web Taxonomy 字段。下面可以开始向其导入内容。

转到 Structure -> Feeds importers,编辑您的导入器。

将 about:itemid 樱红色映射到相关模块 Web Term ID,然后单击 Add。

再次找到您的 Source 1 Tutorial import,单击 Import 选项卡。此时将看到相关模块已经添加,如 图 14 所示。

图 14. 使用相关模块更新节点

现在,您已经完整地配置了导入设置,接下来就可以创建多个 Tutorial Import 节点,从多个站点导入数据。(创建一个 Tutorial import 节点,并添加 Source 2 源。)所导入的全部数据现在都采用 Drupal 能够理解的一种结构化方式。您可以轻松设置用户界面,从而浏览整个教程集合的各个方面。

超越 Microdata Import

Microdata Import 有助于跨组织边界共享知识。然而,有时仅仅使用用 Microdata Import 还不够。Microdata Import 假设您正在导入的页面与您的站点中的页面之间存在一对一的关系。这适用于上述场景,因为您只需要使用教程页面本身提供的教程相关信息。

然而,在某些时候,您可能希望在不同的站点中发布内容的不同人员能够添加关于同一项目的一些信息。例如,如果一所大学内的某位教授兼任两个系中的职务,每个系都应能在其自己的站点中添加有关该教授的信息,而且无需与另外一个系协调。尽管您可以配置源代码和源导入器,通过 Microdata Import 来实现此操作,但还有更便捷的实现方法。

方法之一就是将微数据转为 RDF。HTML Data Task Force 目前正在最终敲定微数据映射到 RDF 的规范草案。这样的映射会使 MicrodataPHP 库等解析器能够以可靠的方式通过微数据标记的页面生成 RDF。Gregg Kellogg(负责领导制定映射规范的工作)开发的 RDF Distiller 工具已经实现了此映射。RDF distiller 是以 Ruby gem 的形式提供的。Kellogg 也在他的网站中发布了一个 API。

结束语

确定如何跨组织和技术边界启用协作式 Web 内容创作是 IT 面临的主要挑战之一。通过在 HTML 本身之中嵌入内容的结构,微数据可以帮助松散耦合的人员和组织就联合项目进行协调。最重要的是,协作者可以为通用产品做出贡献,而且不会失去选择自己的框架的自由度,即便该框架仅仅是手动编码的 HTML 也是如此。

相关文章

深度解析:清理烂代码
如何编写出拥抱变化的代码
重构-使代码更简洁优美
团队项目开发"编码规范"系列文章
相关文档

重构-改善既有代码的设计
软件重构v2
代码整洁之道
高质量编程规范
相关课程

基于HTML5客户端、Web端的应用开发
HTML 5+CSS 开发
嵌入式C高质量编程
C++高级编程
 
分享到
 
 
     


十天学会DIV+CSS(WEB标准)
HTML 5的革新:结构之美
介绍27款经典的CSS框架
35个有创意的404错误页面
最容易犯的13个JavaScript错误
设计易理解和操作的网站
更多...   


设计模式原理与应用
从需求过渡到设计
软件设计原理与实践
如何编写高质量代码
单元测试、重构及持续集成
软件开发过程指南


东软集团 代码重构
某金融软件服务商 技术文档
中达电通 设计模式原理与实践
法国电信 技术文档编写与管理
西门子 嵌入式设计模式
中新大东方人寿 技术文档编写
更多...