vishia - Zmake intern

vishia - Zmake intern

Inhalt


Topic=.Zmake_intern.

pStyle=std

.

Topic=.ZmakeExpand.

pStyle=std

This text file contains all hints to write and expand similar applications of Zmake.

1 Parsen mit ZmakeStd.zbnf

Topic=.Zmake_intern.ZmakeStd.zbnf.

pStyle=std

Dieser Abschnitt beschreibt, wie das ZBNF-Script:_xsl/ZmakeStd.zbnf funktioniert. Der Artikel bezieht sich gegebenenfalls nicht auf den letzten Stand, das ZBNF-Script soll, ein Grundverständnis vorausgesetzt, ansonsten selbstdokumentierend sein.

Die erste aktive Zeile

 Zmake::=<*|ZMAKE_RULES?> ZMAKE_RULES:  { \$<variable>; | <routine>; } \e.

definiert zunächst den Namen des Toplevel-XML-Elements als Zmake. Mit dem <*|ZMAKE_RULES?> werden dann alle Zeichen überlesen bis zur angegebenen Zeichenfolge. Diese wird dann als Terminalmorphem danach auch verlangt.

Das gesamte Script besteht aus einer Folge von $<variable>; oder <routine>. Beide Metamorpheme = Syntaxkomponenten sind danach definiert:

1.1 variable

Topic=.Zmake_intern.ZmakeStd.zbnf..

pStyle=std

Eine Variable wird wie folgt definiert:

 variable::=<$?@name> = fileset ( <fileset> ).
 fileset::= {<?file> [<""?!prepFilePath>|<*\ \r\n,)?!prepFilePath>] ? , | + }.

Eine Variable besteht aus einem Bezeichner (<$?@name>), gefolgt von einem = und fileset(...). Etwas anderes ist derzeit nicht vorgesehen. Das <fileset> ist danach definiert:

Ein fileset besteht aus einer beliebigen Wiederholung von Filenamen, dazwischen ein , oder +. Ein fileset erzeugt pro Fileangabe ein XML-Element <file>. Ein filename kann entweder in Anführungszeichen stehen <""?!prepFilePath> oder ist eine Zeichenfolge bis ausschließlich einem Leerzeichen oder Zeilenendezeichen <* ,)?!prepFilePath>. Alles, was dazwischen steht, wird mit der Syntax prepFilePath geparst:

1.2 prepFilePath

Topic=.Zmake_intern.ZmakeStd.zbnf..

pStyle=std

Diese Syntaxvorschrift wird benutzt, um eine vorher ermittelte Teilzeichenkette, die Filepathangabe, auseinanderzunehmen.

 prepFilePath::=<$NoWhiteSpaces><! *?>
   [<!.?@drive>:]                              ## only 1 char with followed : is a drive like D:
   [<*:?@pathbase>[?:=]:]                      ## all until : is the pathbase, not part of the
   [<stringtolastinclChar/\\?@path>]           ## all until \\ or / is the path part of the file
                                               ## now the file can be given in several ways:
   [ **<?@allTree><*?ext>                      ## ** means: all files also in subfolders. The rest after** is extension.
   | *<?@someFiles><*?@ext>                    ## * means: Some files or placeholder for the name. The rest after * is extension.
   | <stringtolastExclChar.?@file><*?@ext>     ## or a filename and a extension if a . is found
   | <*?@file>                                 ## or only a file if no . is found.
   ]<! *?>.

Mit <$NoWhiteSpaces> wird erstmal die Wirkung der Whitespaces in der Syntaxvorschrift ausgeschaltet. Es sind also nirgends Whitespaces zulässig. Aber am Anfang werden Leerzeichen überlesen, ausgedrückt mit dem RegularExpression <! *?>.

Danach kann ein beliebiges Zeichen folgen: RegularExpression <!.?@drive>. Wenn darauf ein : folgt, dann ist das eine Laufwerksangabe, im Xml als Attribut drive gespeichert. Folgt kein : nach einem Einzelzeichen, dann ist diese Simple-Option nicht erfüllt, es gibt keinen Laufwerksbuchstaben.

Alle danach folgenden Zeichen bis ausschließlich einem : werden als Attribut pathbase gespeichert. Danach muss ein : auch folgen. Ist das nicht der Fall, dann gibt es kein pathbase. Es wird getestet, dass der Inputtext keine Zeichenfolge := enthält, Das wäre eine Verwechslung des : mit dem : von :=.

Danach werden mit <stringtolastinclChar/\?@path> alle Zeichen eingelesen bis einschließlich dem letzten vorgefundenen / oder \. Das ist das Attribut path. Wird kein / oder \ gefunden. dann gibt es kein Attribut path, aber die Syntax ist ok.

Danach wird getestet, ob einer der Optionen passt:

  • Entweder es gibt die Folge **, dann wird das Attribut allTree erzeugt. Alle nachfolgenden Zeichen werden in ext gespeichert.

  • Oder es gibt ein einzelnes *. Dann wird das Attribut someFiles erzeugt. Alle nachfolgenden Zeichen werden in ext gespeichert. Das muss nicht unbedingt eine File-Extension beginnend mit einem Punkt sein, sondern kann auch ein Namensanteil nach dem * sein.

  • oder, wenn kein * gefunden wird, werden alle Zeichen bis ausschließlich dem letzten . als Attribute file gespeichert. Das Attribut file gibt es also nur, wenn kein * gefunden wird. Alles, was nach dem Punkt folgt, einschließlich des ., ist die ext.

Nachfolgende Leerzeichen werden akzeptiert und ignoriert.

1.3 Zerlegen der File-Pathes beim Parsen

Topic=.Zmake_intern.ZmakeStd.zbnf.FilePath.

pStyle=std

TODO

2 Xml-Subroutine genTargetForEachInput

Topic=.Zmake_intern.genTargetForEachInput.

pStyle=std

Das <template name="genTargetForEachInput"> wird von mehreren Zmake-Routinen genutzt. Die gemeinsame Eigenschaft der Routinen ist, dass jeweils eine Konvertierung pro Sourcefile erfolgt. Als Targetfile wird entweder ein Verzeichnis oder eine Wildcard-Angabe erwartet. Das Template organisiert die Abarbeitung und ruft innen pro Sourcefile dann das als Parameter übergebene spezifisch benannte Template auf.

2.1 Anwendung

Topic=.Zmake_intern.genTargetForEachInput..

pStyle=std

Als Beispiel sei die Zmake-Routine file2Html() gegeben, die wie folgt in XSL-Script:_xsl/ZmakeStd.xslp programmiert ist:

 <xsl:template name="file2Html">
   <xsl:call-template name="genTargetForEachInput">
     <xsl:with-param name="genExecForEachInput" select="'exec_file2Html'" />
     <xsl:with-param name="xmlTool_srcFiles" >
       <srcfiles file="{'${env.XML_TOOLBASE}/Xslt.jar'}" />
     </xsl:with-param>
   </xsl:call-template>
 </xsl:template>

Übergeben werden die Parameter

  • genExecForEachInput: Name des Templates, dass die Generierungsbefehle für das ANT-Script generiert, siehe im fortlaufenden Text,

  • xmlTool_srcFiles: Ein XML-Baum mit <srcfiles...>-Elementen, die zusätzlich in den Abhängigkeitstest eingebaut werden sollen. Das sind typischerweise Tool-Files, bei deren Änderung ebenfalls neu generiert werden soll.

Dazu gehört das innen gerufene Template, dessen Name als Parameter genExecForEachInput übergeben wird:

 <xsl:template name="exec_file2Html">
 <xsl:param name="targetfile" />
 <xsl:param name="srcfile" />
 <xsl:param name="xmlInputNode" />
 <xsl:param name="xmlTargetNode" />
   <echo message="gen HTML" />
   <exec dir="{$curDir}" executable= "java" failonerror="false">
     <xsl:variable name="i"><xsl:text>-i</xsl:text><xsl:value-of select="@srcpath" /><xsl:text>/</xsl:text><xsl:value-of select="@srcfile" /></xsl:variable>
     <xsl:variable name="o"><xsl:text>-o../html/</xsl:text><xsl:value-of select="@srcfile" /><xsl:value-of select="@dstext"/></xsl:variable>
     <arg line="{$Classpath}" />
     <arg line ="{'org.vishia.xml.Textfile2Html'}" />
     <arg line="{'-i'}{$srcfile}" />
     <arg line="{'-o'}{$targetfile}" />
   </exec>
 </xsl:template>

Mehr braucht man für diese Zmake-Routine nicht. Der Rest wird vom <template name="genTargetForEachInput"> erledigt.

Das innen gerufene Template bekommt die gezeigten Parameter aus den Informationen des jeweiligen Sourcefiles:

  • targetfile ist der fertig zusammengebaute Name des zu erzeugenden Files als Absolut-Path.

  • srcfile ist der fertig zusammengebaute Name des Sourcefiles als Absolut-Path.

  • xmlInputNode ist die Referenz auf die <input> oder <file>-Element, dass die Informationen zum Inputfile enthält.

  • xmlTargetNode ist die Referenz auf das <target>-Element der Zmake-Routine. Über dieses Element können Parameter eingelesen werden.

Bereits generiert ist pro Inputfile das Haupt-ANT-<target> mit ANT-<target name="isuptodate_... zwecks Test der Neuigkeit des Sourcefiles gegenüber dem Targetfile.

Ebenfalls berücksichtig ist eine Verwendung eines inputSet und eines srcpath: Im anwendenden Zmake-Script können Inputfiles vermittels einer Variablen übergeben werden, die auf ein inputSet abgebildet werden. Schreibt man im Anwender-Zmake-Script:

 $files=fileset(file1.txt, file2.txt);
 ../html/*.*.html := file2Html($files, file3.txt, srcpath="D:/Files");

dann werden alle drei genannten Files berücksichtigt. Das fileset hat den Vorteil, dass diese Auflistung der Files noch an anderer Stelle benutzt werden kann. Diese Arbeit wird von einem <xsl:template name="evaluateInput"> erledigt, was innerhalb <xsl:template name="genTargetForEachInput"> gerufen wird.

Damit braucht in dem spezifisch zu schreibenden Template relativ wenig organisiert werden.

2.2 Realisierung

Topic=.Zmake_intern.genTargetForEachInput..

pStyle=std

Das Template beginnt wie folgt:

 <xsl:template name="genTargetForEachInput">
 <xsl:param name="genExecForEachInput" /><!-- name of the generateExec-Routine. -->
 <xsl:param name="xmlTool_srcFiles" /><!-- contains some <srcfiles ...> elements there are additinal to consider -->
   <xsl:variable name="targetName"><xsl:call-template name="targetName" /></xsl:variable>
   <xsl:variable name="outputPre"><xsl:for-each select="output"><xsl:call-template name="pathPre" /></xsl:for-each></xsl:variable>
   <xsl:variable name="outputPost"><xsl:for-each select="output"><xsl:call-template name="pathPost" /></xsl:for-each></xsl:variable>
   <xsl:call-template name="evaluateInput">
     <xsl:with-param name="call" select="'genTargetForInput'" />
     <xsl:with-param name="p1" select="$targetName" /><!-- base for the some targets names -->
     <xsl:with-param name="p2" select="$outputPre" />
     <xsl:with-param name="p3" select="$outputPost" />
     <xsl:with-param name="p4" select="$genExecForEachInput" />
     <xsl:with-param name="p5" select="." /><!-- xmlTargetNode -->
     <xsl:with-param name="p6" select="$xmlTool_srcFiles" />
   </xsl:call-template>

Es wird also vermittels des template name="evaluateInput" pro Input folgendes Template gerufen, wobei die Parameter p1..05 durchgereicht werden:

 <xsl:template name="genTargetForInput">
 <xsl:param name="p1" /><!-- name of the superior target as basename -->
 <xsl:param name="p2" /><!-- pre-part to build the targetfile name with input file path/name.ext -->
 <xsl:param name="p3" /><!-- post-part,the targetfile name is built with p2+inputfilfile.ext+p3 -->
 <xsl:param name="p4" /><!-- name of the template to generate the ant.xml-code for the exec routine -->
 <xsl:param name="p5" /><!-- The xml target node of the Zmake Routine to get parameters -->
 <xsl:param name="p6" /><!-- additional uptodate src $xmlTool_srcFiles -->
   <xsl:variable name="targetName"><xsl:text>(?$p1?):(?@path?)(?@file?)(?@ext?)</xsl:text></xsl:variable>
   <xsl:variable name="targetUptodate"><xsl:value-of select="$targetName" />_isUptodate</xsl:variable>
   <xsl:variable name="targetfile"><xsl:text>(?$p2?)(?@path?)(?@file?)(?@ext?)(?$p3?)</xsl:text></xsl:variable>
   <xsl:variable name="srcfile"><xsl:call-template name="pathfile" /></xsl:variable>
   <target name="{$targetName}"
     description="{'generate from ZmakeStd.xslp: genTargetForInput: '}{$p4}"
     depends="{$targetUptodate}" unless="{$targetUptodate}">
     <saxon:call-template name="{$p4}">
       <xsl:with-param name="srcfile" select="$srcfile" />
       <xsl:with-param name="targetfile" select="$targetfile" />
       <xsl:with-param name="xmlInputNode" select="." />
       <xsl:with-param name="xmlTargetNode" select="$p5" />
     </saxon:call-template>
   </target>
   <target name="{$targetUptodate}">
     <uptodate property="{$targetUptodate}" targetfile="{$targetfile}">
       <srcfiles file="{$srcfile}" />
       <xsl:copy-of select="$p6" />
     </uptodate>
   </target>
 </xsl:template>

Dieses Template erzeugt als ANT.xml-Ausgabetext zwei <target>, eines zur Ausführung und eines für den Neuigkeitstest. Der targetName wird als Variable zusammengebaut, und zwar aus dem als p1 übergebenen Namen mit nachfolgendem PathFileExt des jeweiligen Inputfiles. Damit ist er eindeutig.

Der targetfile rekrutiert sich aus den Parametern p2 und p3, die übergeordnet aus dem Anteil des targetfile vor und nach einem Wildcard gewonnen werden, oder den Base-Path für die erzeugten Files und deren Extension entsprechen. Dazwischen steht als lokaler Pfad und Filename die Angaben aus den Srcfile.

Der Pfad des srcfile wird dagegen mit einer template-Routine gewonnen und ermittelt den Absolut-Pfad des srcfile. Dazu zählt ein möglicher Basepath und ein ${curDir}, falls der Pfad ansonsten relativ ist. Diese Parameter werden die inneren Routine übergeben und dienen auch als Bausteine für das <target name="{$targetUptodate}">.

Das hier gebaute <target name="{$targetName}" hat innen eine Abfolge, die mit dem vom Anwender bereitgestelltem Template gebaut wird und damit den spezifisch Anteil produziert. Das Anwender-Template wird per Zeichenkette in einer Variablen, $p4, gerufen. Das geht nicht mehr mit den Standard-XSLT-Mitteln sondern benötigt eine Saxon-Erweiterung, die hoffentlich in zukünftigen XSLT-Versionen als Standard verfügbar sein wird. Damit kann als XSLT-Translator nur SAXON (http://www.saxonica.com) von Michael Kay verwendet werden. Das ist aber nicht störend, da Michael Kay selbst im w3c-Konsortium beim XSLT 2.0-Standard wesentlich mitgewirkt hat (das ist also kein propritärer Selbstbau) und den Standard-XSLT-Translator ohne Kosten per Download bereitstellt. Versionen gibt es sogar für die dot-net-Welt.

Im oben begonnenen <xsl:template name="genTargetForEachInput"> geht es aber weiter:

   <xsl:variable name="targetUptodate"><xsl:value-of select="$targetName" />_isUptodate</xsl:variable>
   <xsl:variable name="targetfile"><xsl:text>(?call pathfile:"output"()?)</xsl:text></xsl:variable>
   <target name="{$targetName}"
     description="{'generate from genTargetForEachInput: '}{$genExecForEachInput}"
     unless="{$targetUptodate}">
     <xsl:variable name="depends">
       <xsl:call-template name="evaluateInput">
         <xsl:with-param name="call" select="'genDependsToTarget-dependsInput'" />
         <xsl:with-param name="p1" select="$targetName" /><!-- base for the some targets names -->
       </xsl:call-template>
     </xsl:variable>
     <xsl:attribute name="depends"><xsl:text>(?$depends?)(?$targetUptodate?)</xsl:text></xsl:attribute>
   </target>
   <target name="{$targetUptodate}">
     <uptodate property="{$targetUptodate}" targetfile="{$targetfile}">
       <xsl:call-template name="evaluateInput">
         <xsl:with-param name="call" select="'uptodateSource'" />
       </xsl:call-template>
       <xsl:copy-of select="$xmlTool_srcFiles" />
     </uptodate>
   </target>
   <!-- xxx -->
 </xsl:template>

Im zweiten Teil werden zwei gemeinsame Targets gebaut. Im ersten wird per depends organisiert, dass auch die <target> pro Srcfile aufgerufen werden. Im zweiten <target> wird ein Uptodate-Test für alle Files ...TODO das ist unnötig. Das Target wird aber im depends verlangt, einfach weglassen, dann steht hinten ein Komma. Muss man noch was übergeordnetes tun? Tool-Files aufbereitsen, mit zusätzlichem Input-Paramter?

3 Using <template name="evaluateInput">

Topic=.ZmakeExpand.tpl_evaluateInput.

pStyle=std

The template <template name="evaluateInput"> is a part of file Xml_Toolbase/xsl/ZmakeStd.xslp. It helps to generate the appropriate ant.xml-parts for some input files.

At user level (script.zmake) it may be written

 $inputFiles=fileset
 ( fileA.txt
 , fileB.txt
 , fileC.txt
 );
 ../tmp/*.html := file2Html($inputFiles, fileX, fileY, srcpath="..\src");

The expected result in ant.xml are 5 ANT-targets to convert the 5 named files to theire result files. For the example, to generate ant.xml, the <xsl:template name="file2Html"> calls inside <xsl:call-template name="genTargetForEachInput">. Inside that xsl-template the <xsl:call-template name="evaluateInput"> is called twice: First to produce the ant.xml-targets to translate the 5 files, second to produce the depens-target to force processing of this targets. The <xsl:template name="evaluateInput"> is used some times in the given ZmakeStd.xslp and it is able to use in user xsl-scripts for ant.xml.

The <xsl:template name="evaluateInput"> has some parameters (calling arguments):

  • <xsl:param name="call" />: Name of the xsl-template calling inside for each file,

  • <xsl:param name="p1" /> to p8: Up to eight parameter which are passed forward to the calling xsl-template.

 <xsl:template name="evaluateInput">
 <xsl:param name="call" />
 <xsl:param name="p1" />
 <xsl:param name="p2" />
 ...
 <xsl:param name="p8" />

While calling, the current XML-node should be that node of the XML-translated user.zmake-File, where the input files are named. Normally it is the node of the Zmake-translation-line. The node should contain elements <input file="..."> or <inputSet name=".." />. It is produced parsing any <...?input>-Component in ZBNF with it semantic input::=..., see Xml_Toolbase/xsl/ZmakeStd.zbnf.

The zmake statement may contain a parameter srcpath="srcpath" and a srcext="...". It is translated to the user.zmake.xml and present with a tag <srcpath ,> and <srcext>. It is stored like:

 <xsl:variable name="srcpath1"><!-- The variable will be empty if no srcpath is given in the current node. -->
   <xsl:for-each select="srcpath"><xsl:call-template name="pathbase" />
   </xsl:for-each>
 </xsl:variable>
 <xsl:variable name="srcext" select="srcext" /><!-- my be empty -->

The <xsl:template name="evaluateInput"> processes <xsl:for-each select="input"> and than <xsl:for-each select="inputSet"> with following actions:

 <xsl:for-each select="input">

A pathbase will be assembled using the called template. This pathbase contains information about a given srcpath="..." parameter, see above, and given pathbase=".." or abspath="..." in the input node. See Topic:_ZmakeExpand.tpl_pathbase.

   <!-- prepare the pathbase regarding a srcpath given above. -->
   <xsl:variable name="pathbase">
     <xsl:call-template name="pathbase" ><xsl:with-param name="srcpath" select="$srcpath1" /></xsl:call-template>
   </xsl:variable>

The named xsl-template by <xsl:param name="call"> is called. Therefore the <saxon:call-template name="{$call}"> is used. The <xsl:param name="p1" /> to p8 are passed to it.

  • The current XML-Node while calling <xsl:param name="call"> is that node, which contains the source file informations: It is either the <input...>-node in the node of the Zmake-translation-line or a <file...>-node in the <inputset>-variables node. This current node is able to use by the called xsl-template.

  • The path to the source file regarding any srcpath etc (see above) are provided as <xsl:with-param name="srcfile" >. So the users xsl-template can use the path without any additional effort.

   <saxon:call-template name="{$call}">
     <xsl:with-param name="pathbase" select="$pathbase" />
     <xsl:with-param name="srcfile" >
       <xsl:value-of select="$pathbase" />
       <xsl:call-template name="localPathfile" />
       <xsl:value-of select="$srcext" />
     </xsl:with-param>
     <xsl:with-param name="p1" select="$p1" />
     <xsl:with-param name="p2" select="$p2" />
     <xsl:with-param name="p3" select="$p3" />
     <xsl:with-param name="p4" select="$p4" />
     <xsl:with-param name="p5" select="$p5" />
     <xsl:with-param name="p6" select="$p6" />
     <xsl:with-param name="p7" select="$p7" />
     <xsl:with-param name="p8" select="$p8" />
   </saxon:call-template>

While evaluating a fileset, an additional pathbase="..." may be given in the fileset. It is regarded also. The evaluation of a fileset is executed with

 <xsl:for-each select="inputSet">
   <!-- capture a <srcpath> in the whole input set, it is from a fileset( ..., srcpath="...") in user.zmake. -->
   <xsl:variable name="srcpathInputSet">
     <xsl:choose><xsl:when test="string-length($srcpath1) gt 0"><xsl:value-of select="$srcpath1"/>
     </xsl:when><xsl:otherwise>
       <!-- use a <srcpath> in the inputSet if no srcpath in calling level is given. -->
       <xsl:for-each select="srcpath"><xsl:call-template name="pathbase" />
       </xsl:for-each>
     </xsl:otherwise></xsl:choose>
   </xsl:variable>
   <xsl:comment> Generated by ZmakeStd.xslp: evaluateInput-inputSet(srcpathInputSet=<xsl:value-of select="$srcpathInputSet"/>) </xsl:comment>
   <xsl:text>
   </xsl:text>
   <xsl:variable name="nameInputSet" select="@name" />
   <xsl:for-each select="/.//variable[@name=$nameInputSet]/fileset/file">
     <!-- prepare the pathbase regarding a srcpath given above. -->
     <xsl:variable name="pathbase">
       <xsl:call-template name="pathbase" ><xsl:with-param name="srcpath" select="$srcpathInputSet" /></xsl:call-template>
     </xsl:variable>
     <saxon:call-template name="{$call}">
       <xsl:with-param name="pathbase" select="$pathbase" /><!-- KK1 -->
       <xsl:with-param name="srcfile" >
         <xsl:value-of select="$pathbase" />
         <xsl:call-template name="localPathfile" />
         <xsl:value-of select="$srcext" />
       </xsl:with-param>
       <xsl:with-param name="p1" select="$p1" />
  ...etc.

The users xsl-template may be simple, because some informations are given already and it shouldn't be prepared individually. At example, the <xsl:template name="uptodateSource" > inside Xml_Toolbase/xsl/ZmakeStd.xslp is such an simple template. It should only produce the name of the sourcefile for the ant.xml-script. The name is given in <xsl:param name="srcfile">, so it is easy to output. A more complexly xsl-template is the <xsl:template name="genTargetForInput"> which is called at example in the <xsl:template name="file2Html"> for each file. This xsl-template has to produce the ant.xml-target containing the calling java routine, the depends etc., It shouldn't prepare the input file path, it's given. But it should prepare the output file path depending on the input node.

4 The <template name="pathbase">

Topic=.ZmakeExpand.tpl_pathbase.

pStyle=std

This template assembles some informations to provide a base path for files.

 <xsl:template name="pathbase">

A parameter srcpath may contain a given pathbase. The content of this parameter is ignored if the current node contains an absolute path. Elsewhere it is the first base of the path. But if it is empty, the ${curDir}/ is used as start of base path.

The current node may contain an attribute pathbase=..." also, it is the next part of the basepath.

 <xsl:param name="srcpath" select="'${curDir}/'" />
 <!-- actual xml node is input or output, containing @file @path etc. -->
   <xsl:choose><xsl:when test="boolean(@drive) or boolean(@absPath)" >
     <!-- If a @drive or @absPath argument is given, the srcpath isn't use. -->
     <!-- NOTE @absPath is only a flag attribute, it means, the path starts with /, no curDir should used. -->
     <xsl:value-of select="@drive" /><!-- empty if no drive is given! its okay. -->
   </xsl:when><xsl:otherwise>
     <!--regard srcpath only if the path isn't absolute or doesn't start with a drive letter. -->
     <xsl:choose><xsl:when test="string-length($srcpath) gt 0"><xsl:value-of select="$srcpath"/>
     </xsl:when><xsl:otherwise><xsl:text>${curDir}/</xsl:text>
     </xsl:otherwise></xsl:choose>
   </xsl:otherwise></xsl:choose>
   <!-- the core value of pathbase: -->
   <xsl:value-of select="@pathbase" />
   <xsl:if test="@pathbase">/</xsl:if><!-- slash only if @pathbase is given!-->
 </xsl:template>

5 The <xsl:template name="copyFiles">

Topic=.ZmakeExpand..

pStyle=std

This is the common implementation of copy template generation for some variants. The template is called with a parameter:

 <xsl:template name="copyFiles">
 <xsl:param name="mode" select="'+everytime+replace+'" />

which can contain some variant controls:

TODO