タグ別アーカイブ: Node.js

Node.jsのxml2jsでsitemap.xmlを書き出す

GoogleやBingなどの検索エンジンにクロールしてほしいページを指定する場合、サイトマップを表すXMLファイル(以下、sitemap.xml)を配置するのが一般的だが、手動でこれを記述するのはつらいので、通常はPHPなどによって自動生成することが多い。

今回はgulpで静的なhtmlを大量に書き出す案件で、sitemap.xmlが必要になったので、gulpというかNode.jsでsitemap.xmlを書き出す方法をメモしておく。

予備知識

sitemap.xmlのフォーマット

sitemap.xmlのフォーマットは下記のようにシンプルだ。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>http://kenzauros.com/</loc>
    <priority>1</priority>
    <changefreq>always|hourly|daily|weekly|monthly|yearly|never</changefreq>
    <lastmod>2015-09-17</lastmod>
  </url>
  <url>...</url>
</urlset>

基本的にはurlsetというルート要素の下に必要なだけurl要素が並ぶ。

urlの下の要素などに関しては Sitemapsの記述方法 – インフォセンター – Yahoo!検索 などを参照されたい。

Node.jsでのXML書き出し

Node.jsでXMLを生成するにはxml2jsを使う。あまり需要がないのか、情報が少ないが、とりあえず使うだけならそんなに難しくない。

xml2jsをインストールしておく。

npm install xml2js

詳しくは下記ページを参照のこと。

これに加えて、ファイルに書き出すためにfsパッケージも必要だが、これは標準でインストールされているので、jsファイル内でrequireするだけでよい。

ソースコード

xml2jsとfsを使用したsitemap.xmlの書き出しは次のような感じ。

// ルートURL
var baseUrl = 'http://kenzauros.com/';
// 各ページのurl要素
var urls = [];
// lastmod用日付生成
var today = new Date();
var date = today.getFullYear() + '-' + ('0' + (today.getMonth() + 1)).slice(-2) + '-' + ('0' + today.getDate()).slice(-2);
// トップページ
urls.push({ loc:baseUrl, priority:1.0, changefreq:"weekly", lastmod:date });
// 下層ページ
urls.push({ loc:baseUrl+filename, priority:0.6, changefreq:"weekly" });

var fs = require('fs');
var xml2js  = require('xml2js');
// urlsetをルート要素としてXMLビルダーを初期化
var builder = new xml2js.Builder({ rootName : "urlset" });
// urlsをセット
var xml = builder.buildObject({ url : urls });
// xmlns追加
xml = xml.replace(/<urlset>/, '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">')
// ファイル書き出し
fs.writeFile('sitemap.xml', xml, function (err) {
  console.log('Sitemap updated.');
});

簡単な説明

xml2js.Builderを使用することで、JavaScriptのオブジェクトからXMLに直接変換できるので、ソース自体はシンプルになった。

このとき、オブジェクトに配列を含んでいれば、自動的にそのキー名で複数の要素が生成されるので、わかりやすい。

  • url/locは絶対URLで表記するのでbaseUrlに基本となるURLを定義しておく。
  • urlを格納する配列urlsには { loc:baseUrl, priority:1.0, changefreq:"weekly", lastmod:date } のようなオブジェクトをurls.pushでどんどん追加していく。
  • fsとxml2jsをrequireする。
  • xml2js.Buildernewする(ルート要素名(rootName)にurlsetを指定)。
  • builder.buildObjectでurlを格納した配列をxmlに変換。
  • <urlset>タグに名前空間指定がないので追加。
  • fs.writeFileでファイルを書き出す。

名前空間のあたりは多少泥臭いが、xml2jsに名前空間を指定する方法がなさそうなので、これでしのいだ。

以上で所望のsitemap.xmlを得ることができた。