headerbanner

Lekce XSLT transformace a XML Schema validace, aneb jak v PHP vytvořit menu z XML (a nakonec "redakční systém" pro statický web)

Po seznámení s XML Schema pro validaci XML dokumentu a zejména při prvních krocích s XSL transformací je problém se orientovat v tom, odkud kam a proč program postupuje. Orientaci snad pomohou následující texty. Jejich výstupem bude jednoduchý a reálně použitelný "redakční systém" pro generování kostry statického webu, respektive všech jeho stránek s hlavičkami a menu. (Úplné základy XML a XML Schema najdete třeba u Jiřího Koska).

U jednoduchého webu s pár stranami se mnohdy nevyplatí instalovat složitější systém. Část práce při "tvrdém" kódování je ale přece jen užitečné nechat skriptům. Třeba generování menu a příslušných hlaviček s obsahem klíčových tagů pro optimalizaci.

Nejprimitivnější cestou vytvoření tří čtyřstránkového statického webu je Ctrl-C a Ctrl-V. Zkopírujeme tak hlavičku HEAD a menu. V menu pak obvykle musíme ještě na každé stránce zvlášť vyznačit aktivní položku (třídou, případně jedinečným identifikátorem id), abychom právě aktivní stránce mohli přiřadit nějaké zvýraznění položky menu. Co kdybychom ale tohle zvýraznění nechali skriptu? Na 3 strany to je skoro zbytečné, ale co když má web 10 stran, případně chceme víceúrovňové menu? Když k tomu přičtemě, že každá strana by kvůli vyhledávačům měla mít jedinečný tag TITLE, META tag DESCRIPTION a KEYWORDS, už se rýsuje, že "nějak to zautomatizovat" by nebylo od věci. (Jistě - blížíme se k hranici použití nějakého frameworku nebo redakčního systému - ale HTML soubory poskytnou mnohem rychlejší odezvu, oproti redakčním systémům jsou zcela bezpečné a mají další plus pro weby, kde není potřeba aktualizace.)

Nejdřív si definujeme, jaký výstup potřebujeme. Menu je obvykle kódované jako nečíslovaný seznam. Pro odlišení položek pro CSS stylování většinou vystačíme s vyznačením první a poslední položky, například kvůli začátku a konci lišty menu. Pokud se nechceme potýkat s kompatibilitou prohlížečů u parametrů first-child a last-child, zvolíme označení pomocí třídy s hodnotou first nebo last. Další třídou je označení aktivní cesty menu a aktuální položky - to ale na začátek vynecháme.

Pokud hned na začátku budeme počítat i s víceúrovňovým menu (spíš z cvičných důvodů - pro statické weby to většinou není potřeba), požadovaný HTML kód by mohl vypadat takto:

 
<nav><!-- HTML 5 tag označující menu -->
  <ul><!-- celé menu je nečíslovaný seznam -->
    <li class="first"><!-- první položka má třídu "first" -->
      <a href="#">První položka menu</a>
      <ul><!-- první položka má subpoložku -->
        <li>
          <a href="#">1. subpoložka</a>
        </li>
        <li>
          <a href="#" class="first">2. subpoložka</a>
          <ul><!-- druhá subpoložka má sub-subpoložku -->
            <li class="first">
              <a href="#">1. sub subpoložka</a>
            </li>
            <li><!-- nemá třídu, není na začátku skupiny ani na konci-->
              <a href="#" >2. sub subpoložka</a>          
            </li>
            <li class="last">
              <a href="#">3. sub subpoložka</a>
            </li>
          </ul>
        </li>
      </ul>
    </li>
    <li>
      <a href="#" >Druhá položka menu</a>
    </li>
    <li>
      <a href="#" >Třetí položka menu</a>
    </li>
    <li>
      Čtvrtá položka - neodkazující oddělovač bez tagu A
    </li>
    <li class="last">
      <a href="#">Pátá položka menu</a>
    </li>  
  </ul>
</nav>
 

Každé položce menu by měl příslušet jedinečný obsah titulkové lišty prohlížece v tagu TITLE a jedinečný popis strany v META tagu DESCRIPTION. Pak je tu funkční hledisko - každá položka musí mít nějaký text a URL adresu, na kterou se odkazuje. META tag KEYWORDS vyhledávače nejspíš ignorují, ale pro úplnost ho položkám přiřadíme taky. No a pak si můžeme zvolit jakékoli další parametry, které souvisejí přímo a jen s danou stránkou, na kterou položka odkazuje. Takové parametry pak mohou pomoci při programovaní jednoduchého pomocníka k vytváření statických stránek.

Jako základní dokument, obsahující vše zmíněné, zvolíme XML:

 
<menu>
  <menugroup><!--co skupina, to úroveň menu, bude nahrazeno UL tagem -->
    <menuitem><!--položka menu, bude nahrazeno LI tagem -->
      <inanchor>První položka menu</inanchor><!--text v A tagu -->
      <url>index</url><!--parametr href v A tagu -->
      <!--obsah tagu TITLE v sekci HEAD  -->
      <title>Secoh dmychadla - air pump - kompresory</title>
      <!--obsah tagu META name="Description" v sekci HEAD  -->
      <desc>Dmychadla (air pumps) SECOH pro čistírny odpadních vod, vybavení pro ČOV, provzdušňovací elementy, změkčovací zařízení, reverzní osmózy a UV sterilizátory, dávkovací čerpadla, odvlhčovače, dmychadla a vývěvy ESAM</desc>
      <!--obsah tagu META name="Keywords" v sekci HEAD  -->
      <key>SECOH, ESAM, dmychadla, vývěvy, čov, provzdušňovací elementy</key>
      <!--jen pro ukázku - nějaký další parametr strany  -->
      <pagetype>html</pagetype>
      <!--jen pro ukázku - nějaký další parametr strany  -->
      <yesnoinmenu>y</yesnoinmenu>
      <!--jen pro ukázku - jazyk strany  -->
      <langs>cs</langs>
      <menugroup>
        <menuitem>
          <inanchor>1. subpoložka</inanchor>
          <url>produkty-secoh-phoenix</url>
          <title>Secoh air pump dmychadla - kompresory - velkoobchod</title>
          <desc>Dmychadla (air pump) SECOH - velkoobchod s dmychadly pro čistírny odpadních vod, akvaristiku, zahradní jezírka a další použití</desc>
          <key>SECOH, air pump, airpump, dmychadla, čov, sll, el</key>
          <pagetype>html</pagetype>
          <yesnoinmenu>y</yesnoinmenu>
          <langs>cs</langs>
        </menuitem>
        <menuitem>
          <inanchor>2. subpoložka</inanchor>
          <url>indexufuf</url>
          <title>Secoh dmychadla - air pump - kompresory </title>
          <desc>Dmychadla (air pumps) SECOH pro čistírny odpadních vod, vybavení pro ČOV, provzdušňovací elementy, změkčovací zařízení, reverzní osmózy a UV sterilizátory, dávkovací čerpadla, odvlhčovače, dmychadla a vývěvy ESAM</desc>
          <key>SECOH, ESAM, dmychadla, vývěvy, čov, provzdušňovací elementy</key>
          <pagetype>html</pagetype>
          <yesnoinmenu>y</yesnoinmenu>
          <langs>cs</langs>
          <menugroup>
            <menuitem>
              <inanchor>1. sub subpoložka</inanchor>
              <url>ublabla</url>
              <title>Secoh dmychadla - air pump - kompresory </title>
              <desc>Dmychadla (air pumps) SECOH pro čistírny odpadních vod, vybavení pro ČOV, provzdušňovací elementy, změkčovací zařízení, reverzní osmózy a UV sterilizátory, dávkovací čerpadla, odvlhčovače, dmychadla a vývěvy ESAM</desc>
              <key>SECOH, ESAM, dmychadla, vývěvy, čov, provzdušňovací elementy</key>
              <pagetype>html</pagetype>
              <yesnoinmenu>y</yesnoinmenu>
              <langs>cs</langs>
            </menuitem>
            <menuitem>
              <inanchor>1. sub subpoložka</inanchor>
              <url>blibla</url>
              <title>Secoh dmychadla - air pump - kompresory </title>
              <desc>Dmychadla (air pumps) SECOH pro čistírny odpadních vod, vybavení pro ČOV, provzdušňovací elementy, změkčovací zařízení, reverzní osmózy a UV sterilizátory, dávkovací čerpadla, odvlhčovače, dmychadla a vývěvy ESAM</desc>
              <key>SECOH, ESAM, dmychadla, vývěvy, čov, provzdušňovací elementy</key>
              <pagetype>html</pagetype>
              <yesnoinmenu>y</yesnoinmenu>
              <langs>cs</langs>
            </menuitem>
            <menuitem>
              <inanchor>1. sub subpoložka</inanchor>
              <url>blabla</url>
              <title>Secoh dmychadla - air pump - kompresory </title>
              <desc>Dmychadla (air pumps) SECOH pro čistírny odpadních vod, vybavení pro ČOV, provzdušňovací elementy, změkčovací zařízení, reverzní osmózy a UV sterilizátory, dávkovací čerpadla, odvlhčovače, dmychadla a vývěvy ESAM</desc>
              <key>SECOH, ESAM, dmychadla, vývěvy, čov, provzdušňovací elementy</key>
              <pagetype>html</pagetype>
              <yesnoinmenu>y</yesnoinmenu>
              <langs>cs</langs>
            </menuitem>
          </menugroup>
        </menuitem>
    </menugroup>
    </menuitem>
    <menuitem>
      <inanchor>Druhá položka</inanchor>
      <url>produkty-secoh-phoenix</url>
      <title>Secoh air pump dmychadla - kompresory - velkoobchod</title>
      <desc>Dmychadla (air pump) SECOH - velkoobchod s dmychadly pro čistírny odpadních vod, akvaristiku, zahradní jezírka a další použití</desc>
      <key>SECOH, air pump, airpump, dmychadla, čov, sll, el</key>
      <pagetype>html</pagetype>
      <yesnoinmenu>y</yesnoinmenu>
      <langs>cs</langs>
    </menuitem>
    <menuitem>
      <inanchor>Třetí položka</inanchor>
      <url>secoh-nahradni-dily</url>
      <title>Secoh náhradní díly, cívky, membrány, magnety, filtry</title>
      <desc>Secoh velkoobchod a maloobchod s náhradními díly pro dmychadla. Membrány, cívky, magnety, filtry</desc>
      <key>SECOH, air pump, airpump, dmychadla, čov, sll, el, magnety, cívky, membrány</key>
      <pagetype>html</pagetype>
      <yesnoinmenu>y</yesnoinmenu>
      <langs>cs</langs>
    </menuitem>
    <menuitem>
      <inanchor>Čtvrtá položka - neodkazující oddělovač</inanchor>
      <url></url>
  </menuitem>
    <menuitem>
      <inanchor>Pátá položka</inanchor>
      <url>esam-dmychadla-vyvevy</url>
      <title>ESAM dmychadla a vývěvy Nymburský</title>
      <desc>ESAM dmychadla - dodávky dmychadel ESAM s bočními kanály. Max. přetlak 80 kPa. Dodává firma Nymburský.</desc>
      <key>ESAM, dmychadla, Nymburský</key>
      <pagetype>html</pagetype>
      <yesnoinmenu>y</yesnoinmenu>
      <langs>cs</langs>
    </menuitem>  
  </menugroup>
</menu>
 

XML je velmi podobný požadovanému výstupu a je otázka, proč místo MENUGROUP nepsat rovnou UL a místo MENUITEM rovnou LI. Jediný důvod je snad větší názornost zvoleného XML. Nové a dosud nepopsané jsou elementy pagetype, yesnoinmenu a langs. Pagetype umožní do statického webu zahrnout třeba jednu dynamicky generovanou stránku s mailovým formulářem, yesnoinmenu umožní generovat i stránky, na které se nebudeme odkazovat z menu, ale přímo z textu stránky, langs pak umožní udělat web vícejazyčný (obsah elementu by pak byl třeba cs,en,de).

Máme tedy v jednom XML souboru popis všech opakujících se položek, které mění pouze svůj obsah. Máme požadovaný tvar menu a víme také, že zbytek bude v sekci HEAD. V příštím článku najdete, jak nejprve XML zkontrolovat a následně jak vygenerovat výstup.