# HG changeset patch # User František Kučera <franta-hg@frantovo.cz> # Date 1341508242 -7200 # Node ID 379a2a893fd190746c542b7e399da1ebc2d4c74d # Parent ae484a54d7fb177decf79f1d50435804851b2145 #20 Skriptování: Makra ve skriptech a Skripty v makrech + výpis verzí z Mercurialu. diff -r ae484a54d7fb -r 379a2a893fd1 vstup/makra/hg-verze.xsl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vstup/makra/hg-verze.xsl Thu Jul 05 19:10:42 2012 +0200 @@ -0,0 +1,60 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xsl:stylesheet version="2.0" + xmlns="http://www.w3.org/1999/xhtml" + xmlns:h="http://www.w3.org/1999/xhtml" + xmlns:s="https://trac.frantovo.cz/xml-web-generator/wiki/xmlns/strana" + xmlns:k="https://trac.frantovo.cz/xml-web-generator/wiki/xmlns/konfigurace" + xmlns:m="https://trac.frantovo.cz/xml-web-generator/wiki/xmlns/makro" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:fn="http://www.w3.org/2005/xpath-functions" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:xs="http://www.w3.org/2001/XMLSchema" + exclude-result-prefixes="fn h s k m xs"> + + <!-- Vypíše verze z verzovacího systému: --> + <xsl:template match="m:hg-verze"> + <xsl:variable name="zadáníSkriptu"> + <!-- + TODO: + Zahazovat XML deklaraci bychom mohli v Javě u všech skriptů… + Nicméně současná dohoda je taková, že skripty vracejí fragment, ne celý dokument, + což má výhodu v tom, že můžou vrátit kus textu a nějakou tu značku + a nemusí to být zabalené v kořenovém elementu. + + --> + <m:skript jazyk="bash" výstup="xml">hg log --style xml | awk '{if(NR>1)print}';</m:skript> + <!-- + Také bychom filtrování mohli provés ve skriptu… + hg log … | xpath -e "//logentry[tag[starts-with(., 'v')]]" 2>/dev/null + …ale to by bylo trochu zbytečně pracné. + --> + </xsl:variable> + + <xsl:variable name="výstupSkriptu"> + <xsl:apply-templates select="$zadáníSkriptu/*"/> + </xsl:variable> + + <table> + <thead> + <tr> + <td>Číslo verze</td> + <td>Datum vydání</td> + </tr> + </thead> + <tbody style="text-align: right;"> + <!-- + Výstup skriptu se bude nacházet v XHTML jmenném prostoru, což je obvykle v pořádku, + ale pro mezivýsledky to není úplně vhodné. + --> + <xsl:for-each select="$výstupSkriptu/h:log/h:logentry[h:tag[starts-with(text(), 'v')]]"> + <tr> + <td><xsl:value-of select="substring(h:tag/text(), 2)"/></td> + <td><xsl:value-of select="format-dateTime(h:date, '[D]. [M]. [Y0001]')"/></td> + </tr> + </xsl:for-each> + </tbody> + </table> + </xsl:template> + +</xsl:stylesheet> + diff -r ae484a54d7fb -r 379a2a893fd1 vstup/skriptování.xml --- a/vstup/skriptování.xml Thu Jul 05 14:27:01 2012 +0200 +++ b/vstup/skriptování.xml Thu Jul 05 19:10:42 2012 +0200 @@ -22,9 +22,11 @@ <p> Díky skriptování můžeme stránky obohatit o prakticky libovolný obsah – - jak prostý text, tak i XHTML fragmenty.<m:podČarou>zapíná se pomocí atributu - <code>výstup="xml"</code> a generátor pak kontroluje správné formátování – - nestane se vám, že byste omylem vygenerovali stránky s překříženými nebo neuzavřenými značkami.</m:podČarou> + jak prostý text, tak i XHTML fragmenty.<m:podČarou> + Zapíná se pomocí atributu <code>výstup="xml"</code> a generátor pak kontroluje správné formátování – + nestane se vám, že byste omylem vygenerovali stránky s překříženými nebo neuzavřenými značkami. + Výchozím jmenným prostorem je XHTML a je dostupný i jmenný prostor pro makra (<code>m</code>). + </m:podČarou> </p> <p> Skriptování ale může být nebezpečné, pokud byste spustili generátor na stránkách, @@ -62,7 +64,7 @@ </tbody> </table> - <h2>Perl</h2> + <h2>Perl – ukázka</h2> <p>Jazyky použité nebo citované na této stránce:</p> <!-- Lepšího výsledku bychom samozřejmě dosáhli pomocí XPath dotazu, @@ -86,7 +88,7 @@ } ]]></m:skript></pre> - <h2>BASH</h2> + <h2>BASH – ukázka</h2> <pre><m:skript jazyk="bash"><![CDATA[ echo -n "Právě je: "; date; @@ -143,6 +145,90 @@ echo "Perex: $XWG_STRANKA_PEREX"; ]]></m:skript></pre> + <h2>Makra ve skriptech</h2> + <p> + XML generované skriptem může také obsahovat makra, která se následně interptetují. + <m:skript jazyk="bash" výstup="xml"><![CDATA[ +echo '<m:skript jazyk="bash">'; # Ty zrůdo! :-) +echo 'echo "Takže můžeš skriptovat, když skriptuješ,";'; +echo '</m:skript>'; + ]]></m:skript> + nebo dělat něco užitečnějšího. + </p> + + <m:skript jazyk="perl" výstup="xml"><![CDATA[ +use strict; +use warnings; + +my $adresar = "vstup/makra"; + +print "<m:diagram nadpis='Uživatelská makra v adresáři $adresar'>\n"; +print " node [shape=\"box\"];\n"; +print " koren [label=\"Uživatelská makra\"];\n"; + +opendir(DIR, $adresar) or die $!; +my $i = 0; +while (readdir(DIR)) { + next if (/^\./); + # Měli bychom ošetřit zvláštní znaky v názvech souborů, + # abychom nezpůsobili chybu GraphVizu. + print "n$i [label=\"$_\"];\n"; + print "koren -> n$i;\n"; + $i++; +} +print "</m:diagram>"; +closedir(DIR); + ]]></m:skript> + + <p>…třeba vygenerovat tento diagram následujícím perlovským skriptem:</p> + + <m:pre jazyk="perl"><![CDATA[ +use strict; +use warnings; + +my $adresar = "vstup/makra"; + +print "<m:diagram nadpis='Uživatelská makra v adresáři $adresar'>\n"; +print " node [shape=\"box\"];\n"; +print " koren [label=\"Uživatelská makra\"];\n"; + +opendir(DIR, $adresar) or die $!; +my $i = 0; +while (readdir(DIR)) { + next if (/^\./); + # Měli bychom ošetřit zvláštní znaky v názvech souborů, + # abychom nezpůsobili chybu GraphVizu. + print "n$i [label=\"$_\"];\n"; + print "koren -> n$i;\n"; + $i++; +} +print "</m:diagram>"; +closedir(DIR);]]></m:pre> + + <p> + Který vložíme zabalený v <code><![CDATA[<m:skript jazyk="perl" výstup="xml"> … </m:skript>]]></code> do stránky. + </p> + <p> + Známá chyba: ve skriptech zatím nefungují poznámky pod čarou (a není jisté, jestli kdy fungovat budou – pravděpodobně by to vyžadovalo vícefázové zpracování). + </p> + + <h2>Skripty v makrech</h2> + <p> + Uvnitř maker můžeme volat<m:podČarou> + Ovšem trochu jiným způsobem, než ve stránkách – + nacházíme se totiž v <em>programu</em> (XSL šablona definující makro) + nikoli v <em>datovém souboru</em> (XML stránka). + </m:podČarou> + jiná makra – mj. skripty. + Toho jsme využili v makru, které generuje tabulku verzí z mercurialu: + </p> + + <m:hg-verze/> + + <p> + Toto makro naleznete v souboru <code>vstup/makra/hg-verze.xsl</code>. + </p> + </text> </stránka> diff -r ae484a54d7fb -r 379a2a893fd1 šablona/funkce/src/cz/frantovo/xmlWebGenerator/Xmlns.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/šablona/funkce/src/cz/frantovo/xmlWebGenerator/Xmlns.java Thu Jul 05 19:10:42 2012 +0200 @@ -0,0 +1,15 @@ +package cz.frantovo.xmlWebGenerator; + +/** + * XML jmenné prostory používané v generátoru + * + * @author Ing. František Kučera (frantovo.cz) + */ +public class Xmlns { + + public static final String XHTML = "http://www.w3.org/1999/xhtml"; + public static final String MAKRO = "https://trac.frantovo.cz/xml-web-generator/wiki/xmlns/makro"; + + private Xmlns() { + } +} diff -r ae484a54d7fb -r 379a2a893fd1 šablona/funkce/src/cz/frantovo/xmlWebGenerator/makra/Skriptování.java --- a/šablona/funkce/src/cz/frantovo/xmlWebGenerator/makra/Skriptování.java Thu Jul 05 14:27:01 2012 +0200 +++ b/šablona/funkce/src/cz/frantovo/xmlWebGenerator/makra/Skriptování.java Thu Jul 05 19:10:42 2012 +0200 @@ -18,6 +18,7 @@ package cz.frantovo.xmlWebGenerator.makra; import static cz.frantovo.xmlWebGenerator.NástrojeCLI.načtiProud; +import static cz.frantovo.xmlWebGenerator.Xmlns.*; import java.io.ByteArrayInputStream; import java.io.File; import java.io.PrintStream; @@ -27,7 +28,10 @@ import java.util.Map; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.transform.Source; +import javax.xml.transform.dom.DOMSource; import org.w3c.dom.Document; +import org.w3c.dom.Node; /** * Provedeme skript a do stránky vložíme jeho výstup. @@ -62,9 +66,15 @@ * @param uriStránky URI aktuálně generované stránky → proměnná prostředí * @param nadpisStránky nadpis stránky → proměnná prostředí * @param perexStránky perex stránky → proměnná prostředí - * @return výstup příkazu + * @return výstup příkazu buď jako textový řetězec nebo jako XML (DOMSource) */ - public static String interpretuj(String skriptText, String skriptSoubor, String jazyk, String výstupníFormát, String uriStránky, String nadpisStránky, String perexStránky) { + public static Source interpretuj(String skriptText, String skriptSoubor, String jazyk, String výstupníFormát, String uriStránky, String nadpisStránky, String perexStránky) throws Exception { + String výstupSkriptu = získejVýstupSkriptu(skriptText, skriptSoubor, jazyk, uriStránky, nadpisStránky, perexStránky); + return vyrobXml(výstupSkriptu, "xml".equals(výstupníFormát)); + } + + private static String získejVýstupSkriptu(String skriptText, String skriptSoubor, String jazyk, String uriStránky, String nadpisStránky, String perexStránky) throws Exception { + try { if (isNeprázdný(skriptSoubor)) { System.err.println("\tInterpretuji skript ze souboru: " + skriptSoubor); @@ -136,7 +146,7 @@ System.err.println("Nicméně skript skončil úspěšně, takže pokračujeme dál."); } - return připravVýstup(výsledek, výstupníFormát); + return výsledek.trim(); } else { System.err.println("--- Standardní výstup skriptu: -----"); System.err.println(výsledek); @@ -146,26 +156,12 @@ throw new Exception("Návratová hodnota: " + p.exitValue()); } } catch (Exception e) { - System.err.println("Došlo k chybě při vykonávání skriptu v jazyce: " + jazyk); + System.err.println("Došlo k chybě při vykonávání skriptu."); System.err.println("--------"); System.err.println(skriptText); System.err.println("--------"); e.printStackTrace(System.err); - return null; - } - } - - private static String připravVýstup(String výsledek, String formát) { - if ("xml".equals(formát)) { - if (zkontrolujXml(výsledek)) { - return výsledek.trim(); - } else { - System.err.println("Chyba v XML generovaném skriptem:"); - System.err.println(výsledek); - return null; - } - } else { - return výsledek.trim(); + throw e; } } @@ -174,19 +170,34 @@ } /** - * @param xml fragment XML vygenerovaný skriptem - * @return true v případě, že výstup je validním fragmentem XML + * @param zadání výstup vygenerovaný skriptem + * @param xmlFormát formát zadání: true = xml fragment | false = prostý text + * @return xml fragment nebo prostý text zabalený do html/body + * @throws Exception */ - private static boolean zkontrolujXml(String xml) { - try { - DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); - DocumentBuilder db = dbf.newDocumentBuilder(); - xml = "<xml>" + xml + "</xml>"; - Document d = db.parse(new ByteArrayInputStream(xml.getBytes())); - return true; - } catch (Exception e) { - e.printStackTrace(System.err); - return false; + private static Source vyrobXml(String zadání, boolean xmlFormát) throws Exception { + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + DocumentBuilder db = dbf.newDocumentBuilder(); + Document d; + + if (xmlFormát) { + try { + zadání = "<html xmlns='" + XHTML + "' xmlns:m='" + MAKRO + "'><body>" + zadání + "</body></html>"; + d = db.parse(new ByteArrayInputStream(zadání.getBytes())); + } catch (Exception e) { + System.err.println("Chyba: Skript vrátil neplatné XML."); + throw e; + } + } else { + d = db.newDocument(); + Node html = d.createElementNS(XHTML, "html"); + Node body = d.createElementNS(XHTML, "body"); + Node text = d.createTextNode(zadání); + body.appendChild(text); + html.appendChild(body); + d.appendChild(html); } + + return new DOMSource(d); } } diff -r ae484a54d7fb -r 379a2a893fd1 šablona/makra/skriptování.xsl --- a/šablona/makra/skriptování.xsl Thu Jul 05 14:27:01 2012 +0200 +++ b/šablona/makra/skriptování.xsl Thu Jul 05 19:10:42 2012 +0200 @@ -18,6 +18,7 @@ --> <xsl:stylesheet version="2.0" xmlns="http://www.w3.org/1999/xhtml" + xmlns:h="http://www.w3.org/1999/xhtml" xmlns:m="https://trac.frantovo.cz/xml-web-generator/wiki/xmlns/makro" xmlns:j="java:cz.frantovo.xmlWebGenerator.makra.Skriptování" xmlns:k="https://trac.frantovo.cz/xml-web-generator/wiki/xmlns/konfigurace" @@ -49,17 +50,7 @@ //s:stránka/s:nadpis/text(), //s:stránka/s:perex/text() )"/> - <xsl:choose> - <xsl:when test="$výstupSkriptu"> - <xsl:choose> - <xsl:when test="@výstup = 'xml'"><xsl:value-of select="$výstupSkriptu" disable-output-escaping="yes"/></xsl:when> - <xsl:otherwise><xsl:value-of select="$výstupSkriptu"/></xsl:otherwise> - </xsl:choose> - </xsl:when> - <xsl:otherwise> - <xsl:message terminate="yes">Při interpretaci skriptu došlo k chybě.</xsl:message> - </xsl:otherwise> - </xsl:choose> + <xsl:apply-templates select="$výstupSkriptu/h:html/h:body/node()"/> </xsl:when> <xsl:when test="$režim = 'zakázat'">