sitemap.xmlについての覚書

主にsitemaps.orgを参考に

sitemap.xmlとは?

サイト内のページを検索エンジンなどのクローラに伝えるための手段。
所定のフォーマットで記述したXMLファイル。サーバ上でアクセスできるようにする。

あくまでクローラのページ収集を助ける目的なので、全てのページを記述する必要はない。っと思う。

サンプル

ざっくりとしたサンプルは以下。基本的にurl要素にクローラに伝えたいページの情報を記述する

<?xml version="1.0" encoding="UTF-8"?>
<urlset
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd"
xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:mobile="http://www.google.com/schemas/sitemap-mobile/1.0"
xmlns:xhtml="http://www.w3.org/1999/xhtml"
>
<url>
<loc>http://www.example.com/aaa </loc>
<lastmod>2016-05-01</lastmod>
<changefreq>weekly</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>http://www.example.com/bbb </loc>
<lastmod>2016-05-01</lastmod>
<changefreq>weekly</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>http://www.example.com/ccc </loc>
<lastmod>2016-05-01</lastmod>
<changefreq>weekly</changefreq>
<priority>0.5</priority>
</url>
</urlset>

url要素に含む内容は以下。最悪locのみ記述すればOK

要素名 必須 コメント
loc 必須 ページのURL
lastmod 省略可 最終更新日。「YYYY-MM-DDThh:mmTZD」時刻は省略可
changefreq 省略可 更新頻度。always,hourly,daily,weekly,monthly,yearly,never
priority 省略可 優先順位。1.0 から 0.1

ガラケー向けのURLを記述する場合

フィーチャーフォン用サイトマップ参照。

フィーチャーフォン用サイトマップは別のnamespaceを読み込んで指定する。
「xmlns:mobile=”http://www.google.com/schemas/sitemap-mobile/1.0“」 で読み込み、該当のURLに「mobile:mobile」を指定する

<?xml version="1.0" encoding="UTF-8" ?>
<urlset
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd"
xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:mobile="http://www.google.com/schemas/sitemap-mobile/1.0"
xmlns:xhtml="http://www.w3.org/1999/xhtml"
>
<url>
<loc>http://mobile.example.com/article100.html </loc>
<mobile:mobile/>
</url>
</urlset>

スマホ向けのURLを記述する場合

設定を検索エンジンに伝える 別々の URL参照。

レスポンシブなどでPC版とスマホ版のURLが同一の場合は、特に気にする必要はない。
スマホ版のURLが異なる場合には、URLの対応をsitemap.xmlに明記する。

「xmlns:xhtml=”http://www.w3.org/1999/xhtml“」 で読み込み、該当のURLに「xhtml:link」と「media」でスマホ向けURLを指定する

<?xml version="1.0" encoding="UTF-8"?>
<urlset
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd"
xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:mobile="http://www.google.com/schemas/sitemap-mobile/1.0"
xmlns:xhtml="http://www.w3.org/1999/xhtml"
>
<url>
<loc>http://www.example.com/page-1/ </loc>
<xhtml:link
rel="alternate"
media="only screen and (max-width: 640px)"
href="http://m.example.com/page-1" />
</url>
</urlset>

複数言語のURLを記述する場合

サイトマップを使用して代替言語ページを指定する参照。

「xmlns:xhtml=”http://www.w3.org/1999/xhtml“」 で読み込み、該当のURLに「xhtml:link」と「hreflang」で言語向けURLを指定する

<?xml version="1.0" encoding="UTF-8"?>
<urlset
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd"
xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:mobile="http://www.google.com/schemas/sitemap-mobile/1.0"
xmlns:xhtml="http://www.w3.org/1999/xhtml"
>
<url>
<loc>http://www.example.com/page-1/ </loc>
<xhtml:link
rel="alternate"
hreflang="de"
href="http://www.example.com/deutsch/"
/>
<xhtml:link
rel="alternate"
hreflang="de-ch"
href="http://www.example.com/schweiz-deutsch/"
/>
<xhtml:link
rel="alternate"
hreflang="en"
href="http://www.example.com/english/"
/>
</url>
</urlset>

サイトマップのサイズが大きくなったり、複数に渡る場合

複数のサイトマップ ファイルを送信できますが、各サイトマップ ファイルにリストする URL は 50,000 個まで、ファイル サイズは 10 MB (10,485,760 バイト) 以下とする必要があります。必要な場合は、サイトマップ ファイルを gzip 形式で 10 MB 以下に圧縮して、サーバーの負荷を軽減できます。50,000 個以上の URL をリストする場合は、複数のサイトマップ ファイルを作成する必要があります。

複数のサイトマップを使用する場合は、サイトマップ インデックス ファイルに各サイトマップ ファイルをリストする必要があります。 サイトマップ インデックス ファイルには、最大で 50,000 個のサイトマップをリストできます。サイズは 10 MB (10,485,760 バイト) 以下に圧縮する必要があります。 また、サイトマップ インデックス ファイルが含まれている必要があります。サイトマップ インデックス ファイルの XML 形式は、サイトマップ ファイルとほぼ同じです。

サイトマップの XML 形式

イメージは以下。

<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/siteindex.xsd"
xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<sitemap>
<loc>http://www.example.com/sitemap1.xml.gz </loc>
<lastmod>2004-10-01T18:23:17+00:00</lastmod>
</sitemap>
<sitemap>
<loc>http://www.example.com/sitemap2.xml.gz </loc>
<lastmod>2005-01-01</lastmod>
</sitemap>
</sitemapindex>

sitemap要素に含む内容は以下。最悪locのみ記述すればOK

要素名 必須 コメント
loc 必須 サイトマップのURL
lastmod 省略可 最終更新日。「YYYY-MM-DDThh:mmTZD」時刻は省略可

そもそも、複数のsitemapを作って通知すれば良いような気がしていて、なぜにsitemapindexを別途作る必要があるのかは謎。

設置について

サイトマップを設置する場所はどこでも構わないが、sitemap.xmlには設置されたディレクトリ配下のURLしか記述できない

また同様にsitemap.xmlを含まれるURLのドメインとは別のドメインのサーバに設置することもできない。

http://example.co.jp/catalog/sitemap.xml に置いた場合は、http://example.co.jp/catalog/ から始まる URL を含めることができますが、http://example.co.jp/images/ から始まる URL を含めることはできません。

サイトマップ ファイルの場所

クローラへの通知について

設置したsitemap.xmlをクローラに通知するには以下の方法がある
– 検索エンジンの送信インターフェースを使用してサイトマップを送信
– サイトマップの場所を robots.txt ファイルで指定
– HTTP リクエストを使用してサイトマップを送信

一番手っ取り早いのは、robots.txtに記述する方法だと思われる。
robots.txtに含む場合は以下のように記述する。複数のsitemap.xmlを指定することも可

Sitemap: http://www.example.com/sitemap-host1.xml
Sitemap: http://www.example.com/sitemap-host2.xml

コマンドラインでXMLファイルを整形する

Cygwin環境で試した結果。他の環境でも使えるらしい

podcast.opmlはxmlファイル。
$ xmllint –format podcast.opml -o podcast.opml

以下、オプションの覚書
$ xmllint
Usage : xmllint [options] XMLfiles …
Parse the XML files and output the result of the parsing
–version : display the version of the XML library used
–debug : dump a debug tree of the in-memory document
–shell : run a navigating shell
–debugent : debug the entities defined in the document
–copy : used to test the internal copy implementation
–recover : output what was parsable on broken XML documents
–huge : remove any internal arbitrary parser limits
–noent : substitute entity references by their value
–noenc : ignore any encoding specified inside the document
–noout : don’t output the result tree
–path ‘paths’: provide a set of paths for resources
–load-trace : print trace of all external entites loaded
–nonet : refuse to fetch DTDs or entities over network
–nocompact : do not generate compact text nodes
–htmlout : output results as HTML
–nowrap : do not put HTML doc wrapper
–valid : validate the document in addition to std well-formed check
–postvalid : do a posteriori validation, i.e after parsing
–dtdvalid URL : do a posteriori validation against a given DTD
–dtdvalidfpi FPI : same but name the DTD with a Public Identifier
–timing : print some timings
–output file or -o file: save to a given file
–repeat : repeat 100 times, for timing or profiling
–insert : ad-hoc test for valid insertions
–compress : turn on gzip compression of output
–html : use the HTML parser
–xmlout : force to use the XML serializer when using –html
–nodefdtd : do not default HTML doctype
–push : use the push mode of the parser
–pushsmall : use the push mode of the parser using tiny increments
–memory : parse from memory
–maxmem nbbytes : limits memory allocation to nbbytes bytes
–nowarning : do not emit warnings from parser/validator
–noblanks : drop (ignorable?) blanks spaces
–nocdata : replace cdata section with text nodes
–format : reformat/reindent the input
–encode encoding : output in the given encoding
–dropdtd : remove the DOCTYPE of the input docs
–pretty STYLE : pretty-print in a particular style
0 Do not pretty print
1 Format the XML content, as –format
2 Add whitespace inside tags, preserving content
–c14n : save in W3C canonical format v1.0 (with comments)
–c14n11 : save in W3C canonical format v1.1 (with comments)
–exc-c14n : save in W3C exclusive canonical format (with comments)
–nsclean : remove redundant namespace declarations
–testIO : test user I/O support
–catalogs : use SGML catalogs from $SGML_CATALOG_FILES
otherwise XML Catalogs starting from
file:///etc/xml/catalog are activated by default
–nocatalogs: deactivate all catalogs
–auto : generate a small doc on the fly
–xinclude : do XInclude processing
–noxincludenode : same but do not generate XInclude nodes
–nofixup-base-uris : do not fixup xml:base uris
–loaddtd : fetch external DTD
–dtdattr : loaddtd + populate the tree with inherited attributes
–stream : use the streaming interface to process very large files
–walker : create a reader and walk though the resulting doc
–pattern pattern_value : test the pattern support
–chkregister : verify the node registration code
–relaxng schema : do RelaxNG validation against the schema
–schema schema : do validation against the WXS schema
–schematron schema : do validation against a schematron
–sax1: use the old SAX1 interfaces for processing
–sax: do not build a tree but work just at the SAX level
–oldxml10: use XML-1.0 parsing rules before the 5th edition
–xpath expr: evaluate the XPath expression, imply –noout

Libxml project home page: http://xmlsoft.org/
To report bugs or get some help check: http://xmlsoft.org/bugs.html

MicroformatsとMicrodata

しばらく聞かなかったMicroformatsの話を久しぶりに聞いたと思ったらMicrodataに取って代わられそうになっているらしい。昔から気になっていたものとしては、ちと残念に思ったので改めて調べてみた。

両者を端的に説明すると、HTMLなどに住所やアドレス帳、レビュー、レシピなどの情報(スキーマ)を明示的に埋め込む仕組み。
seh. Microdata: A Primer SlideShare

そもそも何に使えるのか?

検索エンジンやブラウザなどのクライアントが機械的に情報を収集する際の目安になる。
例えば、Googleの検索結果のリッチスニペットなどに利用されることがある。SEOに、ユーザへのアピールに。

将来的には?

GoogleがWebページから自動的にイベント情報を収集。
Googleで「ライブ」と検索すると、現在地、開催日時を元に地元のライブスケジュールの一覧が検索結果として表示されたり(もうされてるかも)。

どんな情報を明示的に埋め込めるのか?

Googleが対応しているらしいスキーマは以下。
> Google では、次のコンテンツ タイプについてリッチ スニペットがサポートされています:
> ・レビュー
> ・人物
> ・製品
> ・会社と組織
> ・レシピ
> ・イベント
> ・音楽
>
> http://support.googlh.com/webmasters/bin/answer.py?hl=ja&answer=99170
パンくずなども対応している様子。seh. [パンくずリスト - ウェブマスター ツール ヘルプ](http://support.googlh.com/webmasters/bin/answer.py?hl=ja&answer=185417)
Microformats、Microdataいずれも様々なスキーマに対応しているし、追加して言っているが結局のところ大手がどのくらい対応しているかによって使う意味があるかどうかが変わってくる。
→ 大手が対応していないのに情報だけ埋め込んでも使い道がない。今後使われる可能性はあるけど

公式Wiki 仕様(Microformatsで対応しているスキーマ)
Organization of Schemas(Microdataで対応しているスキーマ)

で、どうするか?

・既存のものを対応するように修正するには若干骨が折れるかもしれないが、ポイントポイントに絞れば修正はそう大きくないはず。
・落ち目のMicroformatsよりはMicrodataを採用したほうが将来性がありそう
・MicrodataはHTML5+現在Draft。今後大きく変わる可能性があるし、そもそもHTML5じゃないと使えない
 ・たぶんGoogleのことなのでXHTMLなどに埋め込んでても問題なく抽出してくれそう / してくれた
 ・XHTMLに書くと普通にエラーで怒られるけど

Microformats

・HTMLに所定のclassを割り振って使用する。取り敢えずClassを対応させればいいので比較的対応は楽
・ただし、入れ子構造を維持しないといけないためHTMLの記述に自由度が減るかも
・既に落ち目
公式Wiki

例 ###

<!-- vCalendarを埋め込んだ例 -->
<div class="vevent">
<a class="url" href="http://www.web2con.com/">http://www.web2con.com/</a>
<span class="summary">Web 2.0 カンファレンス </span>:
<abbr class="dtstart" title="2007-10-05">10月5日</abbr>〜
<abbr class="dtend" title="2007-10-20">19日</abbr>、
<span class="location">アージェントホテル(カリフォルニア州サンフランシスコ)</span>にて。
</div>

Microdata

・HTMl5の関連しようとして定義されているのでHTML5でのみ使用可能。
・比較的入れ子構造を維持する必要がないため、柔軟なHTMLの記述が可能
・HTML5はまだ早い?
公式Draft

例 ###

<!-- eventなどを埋め込んだ例 -->
<div itemscope itemtype="http://data-vocabulary.org/Event">
​<a href="http://www.examplh.com/events/spinaltap" itemprop="url" >
<span itemprop="summary">Spinal Tap</span>
</a>
<img itemprop="photo" src="spinal_tap.jpg" />
<span itemprop="description">新ドラマー加入後の Spinal Tap が
東京で最新のツアーを
開始します。</span>
日時:
<time itemprop="startDate" datetime="2015-10-15T19:00+09:00">10 月 15 日午後 7 時</time>~
<time itemprop="endDate" datetime="2015-10-15T21:00+09:00">午後 9 時</time>
場所:
​<span itemprop="location" itemscope itemtype="http://data-vocabulary.org/​Organization">
​<span itemprop="name">グーグルホール</span>、
​<span itemprop="address" itemscope itemtype="http://data-vocabulary.org/Address">
<span itemprop="region">東京都</span>
<span itemprop="locality">港区</span>
<span itemprop="street-address">六本木</span>
</span>
<span itemprop="geo" itemscope itemtype="http://data-vocabulary.org/​Geo">
<meta itemprop="latitude" content="37.774929" />
<meta itemprop="longitude" content="-122.419416" />
</span>
</span>
カテゴリ: <span itemprop="eventType">コンサート</span>
<span itemprop="ticketAggregate" itemscope itemtype="http://data-vocabulary.org/Offer-aggregate">
チケット販売価格: <span itemprop="lowPrice">2,000 円</span>~<span itemprop="highPrice">2,500 円</span>
<span itemprop="currency" content="JPY" />
販売枚数: <span itemprop="offerCount">2,000</span> 枚
<a href="http://www.examplh.com/events/spinaltap/alltickets" itemprop="offerurl">
http://googlh.com/ticket</span>購入できるチケットをすべて見る</a>
</span>
<span itemprop="tickets" itemscope itemtype="http://data-vocabulary.org/Offer">
<a href="http://www.examplh.com/events/spinaltap/presale" itemprop="offerurl">前売りチケット</a>
<span itemprop="price">2,000 円</span><span itemprop="currency" content="JPY" />
販売期限: <time itemprop="priceValidUntil" datetime="2015-11-10">2015 年 11 月 10 日</time>
(販売枚数: <span itemprop="quantity">1000</span>)
</span>
<span itemprop="tickets" itemscope itemtype="http://data-vocabulary.org/Offer">
<a href="http://www.examplh.com/events/spinaltap/tickets" itemprop="offerurl">定価チケット</a>
<span itemprop="price">2,500 円</span><span itemprop="currency" content="JPY" />
</span>
</div>

例 ###

<!-- パンくずを埋め込んだ例 -->
<div itemscope itemtype="http://data-vocabulary.org/Breadcrumb">
<a href="http://www.examplh.com/dresses" itemprop="url">
<span itemprop="title">洋服</span>
</a> ›
</div>
<div itemscope itemtype="http://data-vocabulary.org/Breadcrumb">
<a href="http://www.examplh.com/dresses/real" itemprop="url">
<span itemprop="title">ドレス</span>
</a> ›
</div>
<div itemscope itemtype="http://data-vocabulary.org/Breadcrumb">
<a href="http://www.examplh.com/clothes/dresses/real/green" itemprop="url">
<span itemprop="title">緑のドレス</span>
</a>
</div>

参考

リッチ スニペット(microdata、microformats、RDFa) – ウェブマスター ツール ヘルプ
MicroformatsとMicrodataの違いについて : Web Design KOJIKA17
HTML5 の microdata について調べた « blog.udzura.jp
コーディングとSEOの概念が変わるかもしれない、Microdataについての概要 : Web Design KOJIKA17
Microdata + schema.org を実際に使ってみる – terkel.jp
Rich Snippets Testing Tool

GeoRSSについて

GeoRSSは、RSS(Atom 1.0、RSS 2.0、RSS 1.0)のエントリー中に緯度経度を追加するための規格。XMLの名前空間として宣言して使用する。
GeoRSS – Wikipedia, the free encyclopedia

埋め込む種類

単純な例

単純に一点の地図座標を埋め込む場合は、<georss:point>で埋め込む。緯度と経度はスペース区切り

<georss:point>33.591325 130.399065</georss:point>

複雑な例

gml – GeoRSSを参照すると以下のような埋込みが可能
・Point
・Line
・Polygon
・Box

ひとつの記事に複数の地図座標を埋め込めるかについては、現在策定中の様子。ただし、最終更新が2010年8月なので、何らかの理由で頓挫しているのかもしれない
[Roadmap - GeoRSS](http://georss.org/Roadmap)

RSSに埋め込んだ例

・名前空間を追加
・georss:point要素を追加

  <?xml version="1.0" encoding="UTF-8" ?>
<rss
version="2.0"
xmlns:georss="http://www.georss.org/georss"
>
<channel>
<title>サイト名</title>
<link>サイトURL</link>
<description>サイトの説明文</description>
<item>
<title>記事タイトル</title>
<link>記事URL</link>
<guid>記事ID</guid>
<description>記事紹介文</description>
<pubDate>記事公開日時</pubDate>
<georss:point>緯度 経度</georss:point>
</item>
</channel>
</rss>

Google Mapにプロットする

Google Map APIを使ってGoogleMap上にプロットできる

// The GGeoXml constructor takes a URL pointing to a KML or GeoRSS filh.
// You add the GGeoXml object to the map as an overlay, and remove it as an overlay as well.
// The Maps API determines implicitly whether the file is a KML or GeoRSS filh.
var map;
var geoXml;
function initialize() {
if (GBrowserIsCompatible()) {
map = new GMap2(document.getElementById("map_canvas"));
geoXml = new GGeoXml("http://mapgadgets.googlepages.com/cta.kml");
map.addControl(new GLargeMapControl());
map.setCenter(new GLatLng(41.875696,-87.624207), 11);
map.addControl(new GLargeMapControl());
map.addOverlay(geoXml);
}
}

詳しくはKML オーバーレイと GeoRSS オーバーレイを参照

コントローラー内でXMLを整形して表示する

Xml::Serializerがヘルパーなので、App::importで呼び出した後に使用する

|php|
// コントローラーの中だと思いねぇ
function hoge() {
$data = $this->Sample->find(“all”);
$this->_toXml($data, “samples”);
}

function _toXml($data, $root_element=”root”) {
App::import(‘Helper’, “xml”) ;

$xml = new XmlHelper();
$options = array();

$options[‘root’] = $root_element; // ルート要素
$options[“format”] = “tags”; // 値を属性にするか、タグにするか。今回はタグ
$options[“cdata”] = false; // 値をCDATAで囲むかどうか。今回は囲まない
$options[“slug”] = true; // 要素名を大文字にするかどうか。今回は小文字に統一

Configure::write(‘debug’, 0);
header(“Content-Type: application/xml”);
echo $xml->header() . “\r\n”;
echo $xml->serialize($data, $options);

exit;
}
||<

PEAR, XML

簡単な例

|php|
<?php
require_once ‘XML/Unserializer.php’;

$options = array(
"indent"    => " ",
"linebreak" => "\n",
"typeHints" => false,
"addDecl"   => true,
"encoding"  => "UTF-8",
"rootName"  => "feed",
XML_SERIALIZER_OPTION_ROOT_ATTRIBS => array('xmlns' => 'http://www.w3.org/2005/Atom'),
//"defaultTagName" => "info",
XML_SERIALIZER_OPTION_ATTRIBUTES_KEY => '_attributes',
XML_SERIALIZER_OPTION_CONTENT_KEY => '_content',
);
$serializer = new XML_Serializer($options);
$atom = array(
"title"   => "atyks's blog",
"link"    => array(
'_attributes' => array('href' => Router::url("/", true)),
'_content'    => ''
),
"updated" => date("Y-m-d\TH:i:s"),
"author"  => "atyks",
"entry"   => $data["entry"],
);
$serializer->serialize($atom);
$xml = $serializer->getSerializedData();

?>

||<

tips

属性を指定するには、XML_SERIALIZER_OPTION_ATTRIBUTES_KEYとXML_SERIALIZER_OPTION_CONTENT_KEYを使う