headerbanner

XSLT - proč generuje prázdný namespace

Na problém s generováním xmlns="" jsem narazil při transformaci XML struktury webu do podoby sitemap. XSLT procesor se mi zdál nějak příliš pečující, ale on je jen navýsost logický.

Jmenný prostor souboru sitemap je http://www.sitemaps.org/schemas/sitemap/0.9.V XSLT šabloně jsem tedy vygeneroval kořenový element s tímto jmenným prostorem a následně elementy url:

 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
...
<xsl:template match="menu" >      
    <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
    <xsl:apply-templates />
    </urlset> 
</xsl:template>
...
<xsl:template match=... >      
    <url>
    <xsl:apply-templates />
    </url> 
</xsl:template>
...
 

Jenže kód generoval následující výstup:

 
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url xmlns="">
    <loc>http://www.newsroom.cz/microweb/index</loc>
    <lastmod>2-2-2013</lastmod>
    <changefreq>weekly</changefreq>
    <priority>1</priority>
  </url>
 

Proč mi tam cpe ten prázdný jmenný prostor, když v instrukcích nic takového není?!!! Navíc to není jen nezávadná nadbytečnost, ale chyba, protože element url musí patřit do jmenného prostoru sitemap.

Jenže - XSLT šablona je sama o sobě XML souborem. V otvírací značce kořenového elementu xsl:stylesheet má definovaný namespace xsl a jinak nic, tudíž všechny elementy uvnitř bez namespace, tedy bez předpony před jménem, patří do defaultního prázdného namespace. Výstup z transformace to pouze akceptuje a přiřadí elementu tento prázdný jmenný prostor, byť šablona sama o sobě zdánlivě nic takového negeneruje.

Stačí se prostě podívat na XSLT šablonu jako na XML soubor. V něm má element urlset vlastní jmenný prostor http://www.sitemaps.org/schemas/sitemap/0.9, element url má defaultní prázdný prostor, XSLT tuto skutečnost jen "opakuje" a vtělí ji do výstupu.

Řešením je přiřadit jmenný prostor všem elementům podle pravidel pro XML již v kořenovém elementu a nechat XSLT, aby tento jmenný prostor sama přiřadila výstupnímu kořenovému elementu urlset:

 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
...
<xsl:template match="menu" >      
    <urlset>
    <xsl:apply-templates />
    </urlset> 
</xsl:template>
...
 

Výstupem je pak správná sitemap:

 
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>http://www.newsroom.cz/microweb/</loc>
    <lastmod>2-2-2013</lastmod>
    <changefreq>weekly</changefreq>
    <priority>1</priority>
  </url>
  ...
</urlset>
 

(Chyba tedy byla - jako vždy - mezi klávesnicí a židlí.)