Views で XML サイトマップを作る

ウェブサイトの構成によっては、そのすべてのページを Google などの検索エンジンが検出できない場合があります。そのような場合は、XML サイトマップを作成し、その存在を知らせることで、サイトの構成を検索エンジンに正しく伝えることが出来ます。

図1

XML サイトマップとは、sitemaps.org の定めるフォーマットに沿って書かれた XML ドキュメントのことです。Drupal には、XML サイトマップを作成するためのサードパーティー製モジュールがいくつか存在しますが、ここではそういったモジュールは使わずに、「Views で XML サイトマップを作る」ということをやってみたいと思います。

Views には RSS を生成する機能があります。今回作成する XML サイトマップは、これに近いものです。RSS の表示は views_plugin_display_feed.inc(/sites/all/modules/views/plugins/views_plugin_display_feed.inc)というディスプレイプラグインが担っています。今回はこれを参考に、XML 用のディスプレイプラグインを作成します。プラグインの内容は以下のようになります。

<?php
/**
 * @file
 * XML ディスプレイプラグイン。
 */

/**
 * XML サイトマップのような、XML ドキュメントの出力を行います。
 * @ingroup views_display_plugins
 */
class custom_plugin_display_xml extends views_plugin_display_page {
  function uses_breadcrumb() { return FALSE; }

  /**
   * ここで NULL を返すことで、Drupal はページ全体の通常の生成過程は
   * 行わず、内容のみを表示させることが出来ます。
   */
  function execute() {
    $output = $this->view->render();
    if (empty($output)) {
      return drupal_not_found();
    }

    // ヘッダー情報を追加
    drupal_add_http_header('Content-Type', 'application/xml; charset=utf-8');
    print $output;
  }

  function preview() {
    if (!empty($this->view->live_preview)) {
      return '<pre>' . check_plain($this->view->render()) . '</pre>';
    }
    return $this->view->render();
  }
}

これを、カスタムモジュール内の views フォルダ(/sites/all/modules/custom/custom/views/)に custom_plugin_display_xml.inc として配置します。(※ views フォルダが無い場合は、作成してください。カスタムモジュールをまだ作成していない場合は、カスタムモジュールの作り方を参考に、作成&有効化してください。)

プラグインの場所を Views に知らせるために、カスタムモジュールの .info ファイル(/sites/all/modules/custom/custom/custom.info)に以下の行を追加します。

files[] = views/custom_plugin_display_xml.inc

次に、プラグインの内容を Views に伝えるため、モジュール名.views.inc ファイルをカスタムモジュールの views フォルダに設置し(/sites/all/modules/custom/custom/views/custom.views.inc)、そこに hook_views_plugins() を実装します。

/**
 * hook_views_plugins() の実装
 */
function custom_views_plugins() {
  $plugins = array(
    'display' => array(
      'custom xml' => array(
        'title' => t('Custom Xml'),
        'help' => t('xml ドキュメントを生成します。'),
        'handler' => 'custom_plugin_display_xml',// さきほど作成したディスプレイプラグインの名前です。
        'theme' => 'views_view',
        'uses hook menu' => TRUE,
        'use ajax' => FALSE,
        'use pager' => FALSE,
        'accept attachments' => FALSE,
        'admin' => t('Custom Xml'),
        'help topic' => 'display-xml',
      ),
    ),
  );

  return $plugins;
}

次に、これらの設定を適用させるため、カスタムモジュールに hook_views_api() を実装します。

/**
 * hook_views_api() の実装
 */
function custom_views_api() {
  return array(
    'api' => 3.0,
    'path' => drupal_get_path('module', 'custom') .'/views',
    'template path' => drupal_get_path('module', 'custom') .'/views/templates',
  );
}

ここまで完了したら、モジュール管理ページ(「管理」 > 「モジュール」)から、画面下「設定を保存」ボタンをクリックして、モジュールの設定を再構築します。そのあと、「管理」 > 「環境設定」 > 「開発」 > 「パフォーマンス」から、「すべてのキャッシュをクリアー」ボタンをクリックして、キャッシュをクリアしてください。

これで、Views に XML ドキュメントを出力させる準備が出来ました。(※ 難しいのはここまでです。ここからは通常の Views の操作に入ります。)

図2

「管理」 > 「サイト構築」 > Views にアクセスし、「Add new view」をクリック。

図3

View name に「XML サイトマップ」、システム内部名称に「sitemap_xml」と入力、表示のところは「コンテンツ」 of the 「すべて」となるように選択します。「Create a page」のチェックを外し、「Continue & edit」ボタンをクリックします。

図4

ビューの設定画面です。ディスプレイの「+Add」ボタンをクリックすると、今作成した「Custom Xml」ディスプレイが選択肢に入っているので、クリックしてください。

図5

「Custom Xml」ディスプレイの設定画面になりました。真ん中の PAGE SETTINGS のところ、パスに「sitemap.xml」と入力し、画面右上、「保存」ボタンをクリックし、とりあえず設定を保存します。

図6

「/sitemap.xml」にアクセスすると、上のように表示されると思います(Chrome の場合)。プラグインの設定どおり、Drupal の通常のページ生成処理は行われず、ビューの内容のみが出力されています。ヘッダー情報に 'application/xml' と指定しているので、ブラウザでは HTML としてのレンダリングは行われず、XML 文書として、タグがそのまま表示されています。

sitemaps.org のフォーマットに沿って、全体のマークアップを整形します。もういちど、ビューの設定画面に戻ってください。

図7

画面右側、Advanced エリアをクリックして開き、Theme: information のリンクをクリック。

図8

テーマに関する情報が表示されます。このうちの Display output というのは、ビュー全体に適用されるテーマです。横に並んでいる .tpl.php で終わる文字列の集合は、テンプレートファイルとして適用され得る名前を、適用範囲の広い順に並べられたものです。太字のものが、現在適用されているテンプレートの名前です。ここでは「XML サイトマップ」ビューだけに適用されるテンプレートを作成するため、views-view--sitemap-xml.tpl.php という名前のファイルを、カスタムモジュールの views > templates フォルダ内(/sites/all/modules/custom/custom/views/templates/)に配置してください(※ templates フォルダが無い場合は、作成してください)。内容は、以下のようになります。

<<?php print '?xml '; ?>version="1.0" encoding="UTF-8"<?php print '?'; ?>>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">

  <url>
    <loc><?php print $GLOBALS['base_url'] . $GLOBALS['base_path']; ?></loc>
    <lastmod><?php print date('c'); ?></lastmod>
    <changefreq>always</changefreq>
    <priority>1.0</priority>
  </url>

  <?php if ($header): ?>
    <?php print $header; ?>
  <?php endif; ?>

  <?php if ($attachment_before): ?>
    <?php print $attachment_before; ?>
  <?php endif; ?>

  <?php if ($rows): ?>
    <?php print $rows; ?>
  <?php endif; ?>

  <?php if ($attachment_after): ?>
    <?php print $attachment_after; ?>
  <?php endif; ?>

  <?php if ($footer): ?>
    <?php print $footer; ?>
  <?php endif; ?>

</urlset>

sitemap.org のフォーマットに従い、全体を <urlset> タグでマークアップしています。以下、<url> タグが続くわけですが、トップページは固定で良いので、ここに直接記述しています。そのほかの動的な部分は、各変数のところに出力されます。図8 のテーマに関する情報の画面下「Rescan template files」ボタンをクリックし、テーマレジストリを再構築したら、/sitemap.xml ページを見てみましょう。

図9

テーマが適用され、全体が <urlset> でマークアップされました。
次に、<url> 属性以下の、各項目を追加していきます。ビューの設定画面に戻ってください。

図10

画面左側、FIELDS の設定を行います。まず、タイトルは使用しないので削除します。(※ 「タイトル」をクリックし、設定画面下「削除」ボタンをクリック。)

図11

タイトルを削除したら、FIELDS の横の「追加」ボタンをクリック。

図12

「コンテンツ: パス」、「コンテンツ: Updated/commented date」、「Global: Custom text」を選択します。これらは XML サイトマップの各 url においてそれぞれ、<loc>、<lastmod>、<changefreq> の項目となります。「Apply (all displays)」ボタンをクリックしてください。

図13

各設定では、「Create a label」のチェックをはずし、少し下の STYLE SETTINGS では、「Customize field HTML」、「Customize label HTML」、「Customize field and label HTML」すべてにチェックを入れ、それぞれ HTML element セレクトボックスに「- なし -」を選択します(※ これで、フィールドの規定のマークアップはすべて取り除かれます)。

図14

コンテンツ: Updated/commented date の設定では、日付の書式に「カスタム」を選択、Custom date format には「c」と入力してください。(※ これで、「2012-12-03T12:15:37+09:00」といったような、ISO 8601 の書式が適用されます。)Global: Custom text では、テキストに「monthly」等、<changefreq> 属性で指定したい値を入力してください。

図15

順番を修正したい場合は、「追加」の脇のボタンをクリックし、「rearrange」をクリック、Rearrange fields の画面でフィールドをドラッグして順番を修正できます。

もうひとつ、各url における <priority> を追加したい場合は、Global: Custom text をもうひとつ追加します。設定は1つめの Custom text と同様にし、テキストには 0.5 など、<priority> 属性で指定したい値を入力してください。

このあたりでいちど設定を保存し、出力を確認してみましょう。

図16

トップページより下の各行が <div> でマークアップされていますが、その中の各フィールドはマークアップが除外され、そのまま出力されています。あといくつかテンプレートを修正し、これらの出力を整えていきます。

「行」のテンプレートを修正してみましょう。<div> タグが適用されているのを、<url> タグに修正します。これは、図8 のところの、Style output のテンプレートになります。views-view-unformatted--sitemap-xml.tpl.php をカスタムモジュールの views > templates フォルダに作成し(/sites/all/modules/custom/custom/views/templates/views-view-unformatted--sitemap-xml.tpl.php)、内容を以下のように修正します。

<?php
/**
 * XML サイトマップ用テンプレート
 * <h3> タグを削除
 * $row のラッパーを <url> タグに。
 */
?>
<?php foreach ($rows as $id => $row): ?>
  <url>
    <?php print $row; ?>
  </url>
<?php endforeach; ?>

次に「パス」フィールドのテンプレートを修正します。これは、図8 のところの、Field コンテンツ: パス (ID: path) のテンプレートになります。views-view-field--sitemap-xml--path.tpl.php をカスタムモジュールの views > templates フォルダに作成し(/sites/all/modules/custom/custom/views/templates/views-view-field--sitemap-xml--path.tpl.php)、内容を以下のように修正します。

<?php
/**
 * $output の前に $GLOBALS['base_url'] を追加し、エンティティのエスケープ処理。
 * <loc></loc> でラップ。
 */
?>
<loc><?php print htmlentities($GLOBALS['base_url'] . $output, ENT_QUOTES, 'UTF-8'); ?></loc>

次に「Updated/commented date」フィールドのテンプレートを修正します。これは、図8 のところの、Field コンテンツ: Updated/commented date (ID: last_updated) のテンプレートになります。views-view-field--sitemap-xml--last-updated.tpl.php をカスタムモジュールの views > templates フォルダに作成し(/sites/all/modules/custom/custom/views/templates/views-view-field--sitemap-xml--last-updated.tpl.php)、内容を以下のように修正します。

<?php
/**
 * <lastmod> でラップ。
 */
?>
<lastmod><?php print $output; ?></lastmod>

次に「Custom text」フィールドのテンプレートを修正します。これは、図8 のところの、Field Global: Custom text (ID: nothing) のテンプレートになります。views-view-field--sitemap-xml--nothing.tpl.php をカスタムモジュールの views > templates フォルダに作成し(/sites/all/modules/custom/custom/views/templates/views-view-field--sitemap-xml--nothing.tpl.php)、内容を以下のように修正します。

<?php
/**
 * <changefreq> でラップ。
 */
?>
<changefreq><?php print $output; ?></changefreq>

次に、もうひとつの「Custom text」フィールドのテンプレートを修正します。これは、図8 のところの、Field Global: Custom text (ID: nothing_1) のテンプレートになります。views-view-field--sitemap-xml--nothing-1.tpl.php をカスタムモジュールの views > templates フォルダに作成し(/sites/all/modules/custom/custom/views/templates/views-view-field--sitemap-xml--nothing-1.tpl.php)、内容を以下のように修正します。

<?php
/**
 * <priority> でラップ
 */
?>
<priority><?php print $output; ?></priority>

これで完了です。テンプレートディレクトリを再構築して、出力を確認してみましょう。

図17

sitemap.org のフォーマットに沿った XML サイトマップが出来上がりました。これは Google などの検索エンジンで、正しく認識されます。

以上、Views で XML サイトマップを生成する「基本」を説明してきましたが、いかがだったでしょうか。これをさらにカスタマイズして、<changefreq> や <priority> をコンテンツタイプごとに設定する、といったことも出来ます(※1)。また、タクソノミータームのページを加えることも出来ます。

それらの応用は、Views の基本的な動作を理解していれば、それほど難しくはありません。頭の体操なので、是非チャレンジしてみてください。


※1 ヒント: FILTER CRITERIA でコンテンツタイプを絞る→「添付」ディスプレイを追加し、メインとは別のフィルターをかける→今回作成した「Custom XML」ディスプレイで、ヘッダー/フッターから、添付ディスプレイを取り込む。

タグ: 
コア: 
Drupal7