Search code examples
xmlxsltxml-namespacesxml-sitemap

XSLT does not work when I include xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"


My Google sitemap renders well through XSLT fine without the xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" in the < urlset > element, however when included, my foreach statement doesn't work and nothing renders in the template. My code's below. Thanks for your help.

XML

<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>{site_url}</loc>
<lastmod>{current_time format="%Y-%m-%d"}</lastmod>
<changefreq>monthly</changefreq>
<priority>0.5</priority>
</url>
</urlset>

XSL

<xsl:template match="/">
<html>
<body>
<h2>Sitemap</h2>
<table border="1">
<tr bgcolor="#9acd32">
  <th>Location</th>
  <th>Last Modified</th>
  <th>Update Frequency</th>
  <th>Priority</th>
</tr>
<xsl:for-each select="urlset/url">
<tr>
  <td><xsl:value-of select="loc"/></td>
  <td><xsl:value-of select="lastmod"/></td>
  <td><xsl:value-of select="changefreq"/></td>
  <td><xsl:value-of select="priority"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>

Solution

  • My Google sitemap renders well through XSLT fine without the xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" in the <urlset> element, however when included, my foreach statement doesn't work and nothing renders in the template

    This is a FAQ.

    XPath treats any unprefixed name as belonging to "no namespace". However, the elements in the provided document belong to the "http://www.sitemaps.org/schemas/sitemap/0.9" namespace -- not to "no namespace".

    Therefore, the following XPath expression doesn't select any node at all:

    urlset/url
    

    Solution:

    Define the "http://www.sitemaps.org/schemas/sitemap/0.9" namespace in the XSLT stylesheet and associate a prefix to it. Then use this prefix with all names that participate in any XPath expression.

    <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:s="http://www.sitemaps.org/schemas/sitemap/0.9"
     exclude-result-prefixes="s"
    >
    
     <xsl:template match="/">
      <html>
        <body>
          <h2>Sitemap</h2>
          <table border="1">
            <tr bgcolor="#9acd32">
              <th>Location</th>
              <th>Last Modified</th>
              <th>Update Frequency</th>
              <th>Priority</th>
            </tr>
            <xsl:for-each select="s:urlset/s:url">
              <tr>
                <td><xsl:value-of select="s:loc"/></td>
                <td><xsl:value-of select="s:lastmod"/></td>
                <td><xsl:value-of select="s:changefreq"/></td>
                <td><xsl:value-of select="s:priority"/></td>
              </tr>
            </xsl:for-each>
          </table>
        </body>
      </html>
     </xsl:template>
    </xsl:stylesheet>
    

    when this transformation is applied on the provided XML document:

    <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
        <url>
            <loc>{site_url}</loc>
            <lastmod>{current_time format="%Y-%m-%d"}</lastmod>
            <changefreq>monthly</changefreq>
            <priority>0.5</priority>
        </url>
    </urlset>
    

    it correctly produces the following result:

    <html>
       <body>
          <h2>Sitemap</h2>
          <table border="1">
             <tr bgcolor="#9acd32">
                <th>Location</th>
                <th>Last Modified</th>
                <th>Update Frequency</th>
                <th>Priority</th>
             </tr>
             <tr>
                <td>{site_url}</td>
                <td>{current_time format="%Y-%m-%d"}</td>
                <td>monthly</td>
                <td>0.5</td>
             </tr>
          </table>
       </body>
    </html>