Googleに登録するサイトマップ(sitemap.xml)の作り方

Google Search Console のサイトマップに、自分のブログの sitemap.xml を登録しておくと、

Google の Bot が巡回して、検索結果に反映してくれる。

WordPress を使用している場合、プラグインで簡単にできるが、

オリジナルのサイトで必要な場合、

どうやって sitemap.xml を作るのか?

まず、メインのファイルとなる「sitemap.xml」を作る。

ドメイン直下の「sitemap」というフォルダにまとめる。

・トップページ : /sitemap/addl-sitemap.xml
・投稿ページ : /sitemap/post-sitemap【任意の番号】.xml
・固定ページ : /sitemap/page-sitemap.xml
・レイアウト設定: /default.xsl

を作る。

sitemap.xml

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="https://【ドメイン】/default.xsl"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
    <sitemap>
        <loc><![CDATA[https://【ドメイン】/sitemap/addl-sitemap.xml]]></loc>
        <lastmod><![CDATA[2021-12-07T02:00:55+00:00]]></lastmod>
    </sitemap>

    <sitemap>
        <loc><![CDATA[https://【ドメイン】/sitemap/post-sitemap1.xml]]></loc>
        <lastmod><![CDATA[2021-11-30T23:58:35+00:00]]></lastmod>
    </sitemap>
    <sitemap>
        <loc><![CDATA[https://【ドメイン】/sitemap/post-sitemap2.xml]]></loc>
        <lastmod><![CDATA[2021-10-30T08:55:24+00:00]]></lastmod>
    </sitemap>
・・・
    <sitemap>
        <loc><![CDATA[https://【ドメイン】/sitemap/page-sitemap.xml]]></loc>
        <lastmod><![CDATA[2021-12-02T04:17:16+00:00]]></lastmod>
    </sitemap>
</sitemapindex>

トップページがこちら。

addl-sitemap.xml

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="https://【ドメイン】/default.xsl"?>
<urlset
    xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
    xmlns:xhtml="http://www.w3.org/1999/xhtml"
>
    <url>
        <loc><![CDATA[https://【ドメイン】]]></loc>
        <lastmod><![CDATA[2021-12-07T02:00:55+00:00]]></lastmod>
        <changefreq><![CDATA[always]]></changefreq>
        <priority><![CDATA[1]]></priority>
    </url>
</urlset>

投稿ページの一覧がこちら。

post-sitemap1.xml

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="https://【ドメイン】/default.xsl"?>
<urlset
    xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
    xmlns:xhtml="http://www.w3.org/1999/xhtml"
>
    <url>
        <loc><![CDATA[https://【ドメイン】/entry/2019/01/29/090644]]></loc>
        <lastmod><![CDATA[2021-03-15T08:07:56+00:00]]></lastmod>
        <changefreq><![CDATA[weekly]]></changefreq>
        <priority><![CDATA[0.7]]></priority>
    </url>
    <url>
        <loc><![CDATA[https://【ドメイン】/entry/2019/01/28/211319]]></loc>
        <lastmod><![CDATA[2021-03-15T08:08:02+00:00]]></lastmod>
        <changefreq><![CDATA[weekly]]></changefreq>
        <priority><![CDATA[0.7]]></priority>
    </url>

</urlset>

投稿数1000件程度を目安に連番でファイルを作った。

例:
post-sitemap1.xml (0001-1000 ページ)
post-sitemap2.xml (1001-2000 ページ)
post-sitemap3.xml (2001-3000 ページ)
・・・

固定ページの一覧がこちら。

page-sitemap.xml

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="https://【ドメイン】/default.xsl"?>
<urlset
    xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
    xmlns:xhtml="http://www.w3.org/1999/xhtml"
>
    <url>
        <loc><![CDATA[https://【ドメイン】/home]]></loc>
        <lastmod><![CDATA[2021-12-02T04:15:28+00:00]]></lastmod>
        <changefreq><![CDATA[weekly]]></changefreq>
        <priority><![CDATA[0.7]]></priority>
    </url>
    <url>
        <loc><![CDATA[https://【ドメイン】/kotei1]]></loc>
        <lastmod><![CDATA[2021-12-02T04:16:04+00:00]]></lastmod>
        <changefreq><![CDATA[weekly]]></changefreq>
        <priority><![CDATA[0.7]]></priority>
    </url>
    <url>
        <loc><![CDATA[https://【ドメイン】/kotei2]]></loc>
        <lastmod><![CDATA[2021-12-02T04:16:56+00:00]]></lastmod>
        <changefreq><![CDATA[weekly]]></changefreq>
        <priority><![CDATA[0.7]]></priority>
    </url>
</urlset>

それぞれのタグの意味は、

loc:ファイルのパス
lastmod:ファイルの更新日
changefreq:更新頻度
priority:優先順位(0.1-1.0)

を表している。

XMLで文書レイアウトを定義するスタイルシートが記述されたファイル 「default.xml」を作る。

default.xsl

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
    version="2.0"
    xmlns:html="http://www.w3.org/TR/html40"
    xmlns:sitemap="http://www.sitemaps.org/schemas/sitemap/0.9"
    xmlns:video="https://www.google.com/schemas/sitemap-video/1.1"
    xmlns:image="https://www.google.com/schemas/sitemap-image/1.1"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
    <xsl:output method="html" version="1.0" encoding="UTF-8" indent="yes"/>

    <xsl:template match="/">
    <xsl:variable name="fileType">
        <xsl:choose>
            <xsl:when test="//sitemap:url">Sitemap</xsl:when>
            <xsl:otherwise>SitemapIndex</xsl:otherwise>
        </xsl:choose>
    </xsl:variable>
    <html xmlns="http://www.w3.org/1999/xhtml">
        <head>
            <title>
                <xsl:choose><xsl:when test="$fileType='Sitemap'">Sitemap</xsl:when>
                    <xsl:otherwise>Sitemap Index</xsl:otherwise>
                </xsl:choose>
            </title>
            <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
            <style type="text/css">
                body {
                    margin: 0;
                    font-family: Helvetica, Arial, sans-serif;
                    font-size: 68.5%;
                }
                #content-head {
                    background-color: #4275f4;
                    padding: 20px 40px;
                }
                #content-head h1,
                #content-head p,
                #content-head a {
                    color: #fff;
                    font-size: 1.2em;
                }
                #content-head h1 {
                    font-size: 2em;
                }
                table {
                    margin: 20px 40px;
                    border: none;
                    border-collapse: collapse;
                }
                table {
                    font-size: 1em;
                    width: 75%;
                }
                th {
                    border-bottom: 1px solid #ccc;
                    text-align: left;
                    padding: 15px 5px;
                    font-size: 14px;
                }
                td {
                    padding: 10px 5px;
                    border-left: 3px solid #fff;
                }
                tr.stripe {
                    background-color: #f7f7f7;
                }
                table td a:not(.localized) {
                    display: block;
                }
                table td a img {
                    max-height: 30px;
                    margin: 6px 3px;
                }
            </style>
            </head>
        <body>
            <div id="content">
                <div id="content-head">
                    <h1>XML Sitemap</h1>
                    <p>
                        生成:  <a href="https://【ドメイン】/" target="_blank">【ドメイン】</a>, これはXMLサイトマップで、GoogleやBingなどの検索エンジンによって使用されることを意図しています。<br/>
                        XML サイトマップの詳細については <a href="https://www.sitemaps.org/" target="_blank" rel="noreferrer noopener">sitemaps.org</a> をご覧ください。                    </p>
                    <p>
                        <xsl:choose>
                            <xsl:when test="$fileType='Sitemap'">
                                このサイトマップには以下が含まれます: <xsl:value-of select="count(sitemap:urlset/sitemap:url)"></xsl:value-of> URL.</xsl:when>
                            <xsl:otherwise>このサイトマップインデックスには以下が含まれます: <xsl:value-of select="count(sitemap:sitemapindex/sitemap:sitemap)"></xsl:value-of> サイトマップ.</xsl:otherwise>
                        </xsl:choose>
                    </p>
                </div>
                <xsl:choose>
                    <xsl:when test="$fileType='Sitemap'">
                        <xsl:call-template name="sitemapTable"/></xsl:when>
                    <xsl:otherwise><xsl:call-template name="siteindexTable"/></xsl:otherwise>
                </xsl:choose>
            </div>
        </body>
    </html>
    </xsl:template>

    <xsl:template name="siteindexTable">
        <table cellpadding="3">
            <thead>
            <tr>
                <th width="50%">URL</th>
                <th>Last Change</th>
            </tr>
            </thead>
            <tbody>
            <xsl:variable name="lower" select="'abcdefghijklmnopqrstuvwxyz'"/>
            <xsl:variable name="upper" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
            <xsl:for-each select="sitemap:sitemapindex/sitemap:sitemap">
                <tr>
                    <xsl:if test="position() mod 2 != 1">
                        <xsl:attribute name="class">stripe</xsl:attribute>
                    </xsl:if>
                    <td>
                        <xsl:variable name="itemURL">
                            <xsl:value-of select="sitemap:loc"/>
                        </xsl:variable>
                        <a href="{$itemURL}">
                            <xsl:value-of select="sitemap:loc"/>
                        </a>
                    </td>
                    <td>
                        <xsl:value-of select="concat(substring(sitemap:lastmod,0,11),concat(' ', substring(sitemap:lastmod,12,5)))"/>
                    </td>
                </tr>
            </xsl:for-each>
            </tbody>
        </table>
    </xsl:template>

    <xsl:template name="sitemapTable">
        <xsl:variable name="sitemapType">
            <xsl:for-each select="/*/namespace::*">
                <xsl:if test="name()='video'">
                    <xsl:choose>
                        <xsl:when test="name()='video'">video</xsl:when>
                    </xsl:choose>
                </xsl:if>
            </xsl:for-each>
        </xsl:variable>

        <table cellpadding="3">
            <thead>
            <tr>
                <th width="50%">URL</th>
                <th>Priority</th>
                <th>Change Frequency</th>
                <th>Last Change</th>
            </tr>
            </thead>
            <tbody>
            <xsl:variable name="lower" select="'abcdefghijklmnopqrstuvwxyz'"/>
            <xsl:variable name="upper" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
            <xsl:for-each select="sitemap:urlset/sitemap:url">
                <tr>
                    <xsl:if test="position() mod 2 != 1">
                        <xsl:attribute name="class">stripe</xsl:attribute>
                    </xsl:if>
                    <td>
                        <xsl:variable name="itemURL">
                            <xsl:value-of select="sitemap:loc"/>
                        </xsl:variable>
                        <xsl:choose>
                            <xsl:when test="sitemap:loc/@language != ''">
                                <a href="{$itemURL}" class="localized">
                                    <xsl:value-of select="sitemap:loc"/>
                                </a> &#160;&#8594; <xsl:value-of select="sitemap:loc/@language"/>
                            </xsl:when>
                            <xsl:otherwise>
                                <a href="{$itemURL}">
                                    <xsl:value-of select="sitemap:loc"/>
                                </a>
                            </xsl:otherwise>
                        </xsl:choose>
                        <xsl:for-each select="./*[@rel='alternate']">
                            <br />
                            <a href="{current()/@href}" class="localized">
                                <xsl:value-of select="@href"/>
                            </a> &#160;&#8594; <xsl:value-of select="@hreflang"/>
                        </xsl:for-each>
                    </td>
                                        <td>
                        <xsl:if test="string(number(sitemap:priority))!='NaN'">
                            <xsl:value-of select="concat(sitemap:priority*100,'%')"/>
                        </xsl:if>
                    </td>
                    <td>
                        <xsl:value-of select="concat(translate(substring(sitemap:changefreq, 1, 1),concat($lower, $upper),concat($upper, $lower)),substring(sitemap:changefreq, 2))"/>
                    </td>
                    <td>
                        <xsl:value-of select="concat(substring(sitemap:lastmod,0,11),concat(' ', substring(sitemap:lastmod,12,5)))"/>
                    </td>
                    <td>
                    </td>
                </tr>
            </xsl:for-each>
            </tbody>
        </table>
    </xsl:template>
</xsl:stylesheet>