BaronGrivet
BaronGrivet

Reputation: 4424

Correct XSLT syntax for Google multilingual sitemaps/ xhtml:link

I have an XML sitemap for a multilingual site that follows Google's specifications for multilingual sitemaps using the xhtml:link tags.

The syntax looks like this:

        <url>
          <loc>http://www.example.com/url-segment/</loc>
          <xhtml:link rel="alternate" hreflang="en" href="http://www.example.com/url-segment/" />
          <xhtml:link rel="alternate" hreflang="de" href="http://www.example.com/de/url-segment/" />
          <xhtml:link rel="alternate" hreflang="fr" href="http://www.example.com/fr/url-segment/" />
          <lastmod>2016-08-09T00:41:57+12:00</lastmod>
          <changefreq>weekly</changefreq>
          <priority>0.9</priority>
        </url>

I'm trying to make this human readable for the client using an XSLT template like this:

  <xsl:for-each select="sitemap:urlset/sitemap:url">
    <tr>
      <td>
        <xsl:variable name="itemURL">
          <xsl:value-of select="sitemap:loc"/>
        </xsl:variable>
      </td>
    <td>
      <xsl:value-of select="concat(sitemap:priority*100,'%')"/>
    </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>
   </tr>
 </xsl:for-each>

Which works without the xhtml:link tags. But I'm not sure how to correctly reference the xhtml:link tags. I've tried something like this:

<xsl:for-each select="xhtml:link">
  <tr>
    <td>
      <xsl:value-of select="xhtml:link@href"/>
    </td>
    <td>
      <xsl:value-of select="xhtml:link@hreflang"/>
    </td>
    <td colspan="2"></td>
  </tr>
</xsl:for-each>

But that's not working.

What is the correct XSLT syntax for looping through/ selecting xhtml:link tags in Google multilingual sitemaps?

Upvotes: 3

Views: 657

Answers (3)

Rich DeBourke
Rich DeBourke

Reputation: 3423

I wanted the same thing as BaronGrivet (a sitemap with xhtml:link tags that displays nicely in a browser). I found an xsl template by Pedro Borges on GitHub that works quite nicely.

Rather than using xsl:for-each to loop through each xhtml link, that template uses xsl:apply-templates (apply-templates processes all of the child nodes of the current node}.

The key parts from Pedro’s template are:

<xsl:template match="/">
    <html>
        <body>
            …
            <xsl:apply-templates/>
            …
        </body>
    </html>
</xsl:template>

<xsl:template match="sitemap:urlset">
    …
    <xsl:for-each select="sitemap:url">
        …
        <xsl:apply-templates select="xhtml:*"/>
        …
    </xsl:for-each>
    …
</xsl:template>

<xsl:template match="xhtml:link">
    <xsl:variable name="altloc">
        <xsl:value-of select="@href"/>
    </xsl:variable>
    <p>
        Alt language version: 
        <a href="{$altloc}">
            <xsl:value-of select="@href"/> 
        </a> 
        –
        <xsl:if test="@hreflang">
            <xsl:value-of select="@hreflang"/> 
        </xsl:if> 
    </p>
</xsl:template>

Pedro's template has a lot more capability than I need (e.g. can list videos), but it was easy enough to edit the template to do what I needed.

Upvotes: 2

BaronGrivet
BaronGrivet

Reputation: 4424

I couldn't get it to recognise/ reference the xhtml:link node using this code:

<xsl:for-each select="xhtml:link">

In the end this approach worked for me:

<xsl:for-each select="./*[@rel='alternate']">
  <tr>
    <td>
      <xsl:value-of select="@href"/>
    </td>
    <td>
      <xsl:value-of select="@hreflang"/>
    </td>
  </tr>
</xsl:for-each>

Upvotes: 3

Joel M. Lamsen
Joel M. Lamsen

Reputation: 7173

You are already in xhtml:link node (in xsl:for-each). Use

<xsl:value-of select="@href"/>

and

<xsl:value-of select="@hreflang"/>

Upvotes: 0

Related Questions