1<?xml version="1.0" encoding="UTF-8"?>
2
3<!--
4### xsl stylesheet used to convert content.xml file from an odt file to dokuwiki syntax
5@license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
6
7@author Greg BELLAMY <garlik.crx@gmail.com> [Gag]
8
9Version 0.2 Alpha 2012-02-15
10  * Adding this comment
11  * Description of parsed markups
12
13Howto :
14  * Support of some dokuwiki plugin will be set by parameters at the begin of this stylesheet
15
16Supported formatting :
17  * headline lvl 1 to 5
18  * paragraph
19  * char :
20    * underline
21    * bold
22    * italic
23  * table (simple one with few fusionned cell, fusion table display the best with an error message)
24  * pictures
25  * list
26
27Supported plugin :
28  * numberedheading : adding numbering to titles
29
30Advice :
31  * The output is directly dependent on the quality of making the input file. The Use of styles is recommanded.
32
33ToDo (next feature):
34  * Add an language support by setting parameters like plugin support
35
36Source :
37  * This stylesheet is an adaptation of the sheet available at http://wiki.lm7.fr/ to translating a odt file format to mediawiki
38
39###
40-->
41
42<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:office="http://openoffice.org/2000/office" xmlns:style="http://openoffice.org/2000/style" xmlns:text="http://openoffice.org/2000/text" xmlns:table="http://openoffice.org/2000/table" xmlns:draw="http://openoffice.org/2000/drawing" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:number="http://openoffice.org/2000/datastyle" xmlns:svg="http://www.w3.org/2000/svg" xmlns:chart="http://openoffice.org/2000/chart" xmlns:dr3d="http://openoffice.org/2000/dr3d" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="http://openoffice.org/2000/form" xmlns:script="http://openoffice.org/2000/script" xmlns:java="http://xml.apache.org/xslt/java">
43  <xsl:output
44    method="text"
45    encoding="utf-8"
46  />
47  <xsl:param
48    name="numberedheadings"
49    value="0"
50  />
51  <xsl:param
52    name="subtable_message">
53    <xsl:text>FIXME : Subtable detected. Formatting must be corrected.</xsl:text>
54  </xsl:param>
55  <!-- Wont work <xsl:param name="cmtopx" value="37.795275591"/>-->
56  <!-- Get toc sources styles to check paragraphe tag with header style in text:p template -->
57  <xsl:variable name="title_style" value="//text:index-source-styles"/>
58  <xsl:strip-space elements="*"/>
59  <!-- Catch the non-content document sections -->
60  <xsl:template match="/XML"/>
61  <xsl:template match="/office:document-content/office:meta"/>
62  <xsl:template match="/office:document-content/office:settings"/>
63  <xsl:template match="/office:document-content/office:script"/>
64  <xsl:template match="/office:document-content/office:font-face-decls"/>
65  <xsl:template match="/office:document-content/office:document-styles"/>
66  <xsl:template match="/office:document-content/office:automatic-styles"/>
67  <xsl:template match="/office:document-content/office:styles"/>
68  <xsl:template match="/office:document-content/office:master-styles"/>
69  <xsl:template match="/office:document-content/office:body/office:text/office:forms"/>
70  <xsl:template match="/office:document-content/office:body/office:text/text:tracked-changes"/>
71  <xsl:template match="/office:document-content/office:body/office:text/sequence-decls"/>
72  <xsl:template match="//text:table-of-content"/>
73
74<!-- Line-break formatting - This is not a paragraph end -->
75  <xsl:template match="//text:line-break">
76    <xsl:text disable-output-escaping="yes">\\ </xsl:text>
77  </xsl:template>
78
79<!-- Headline formatting -->
80  <xsl:template name="titre" match="//text:h">
81    <xsl:param name="level" select="@text:outline-level"/>
82    <xsl:variable name="chaine"><xsl:call-template name="boucle">
83      <xsl:with-param name="debut" select="1" />
84      <xsl:with-param name="fin" select="7 - $level" />
85      <xsl:with-param name="texte" select="'='" />
86    </xsl:call-template></xsl:variable>
87
88    <xsl:value-of select="$chaine"/>
89    <xsl:text disable-output-escaping="yes"> </xsl:text>
90    <xsl:if test="$numberedheadings = '1'"><xsl:text disable-output-escaping="yes">- </xsl:text></xsl:if>
91    <xsl:apply-templates/>
92    <xsl:text disable-output-escaping="yes"> </xsl:text>
93    <xsl:value-of select="$chaine"/>
94    <xsl:text disable-output-escaping="yes">
95
96</xsl:text>
97  </xsl:template>
98
99  <!-- Text blocks
100  Greg - Transcription des paragraphes
101  Déroulé :
102  Mise en variables des éléments (style, contenu)
103  Si le text n'est pas vide
104    Appel de la mise en forme ouvrante
105    Intégration de contenu
106    Appel de la mise en forme sortante
107    Ajout de retour chariot selon les règles de syntaxe Dokuwiki (le première qui match a gagnée)
108    Si cellule d'un tableau avec plusieurs paragraphes : 1 Retour chariot
109    Si cellule d'un tableau : Pas de retour chariot
110    Si élément d'une liste suivi d'un élément : 1 Retour chariot
111    Si dernier élément d'une liste : 2 Retour chariot
112  Si le text est vide
113    On ne fait rien
114  -->
115  <xsl:template match="//text:p">
116    <xsl:if test=".!='' or count(*) &gt; 0">
117      <xsl:variable name="p_style" select="@text:style-name"/>
118      <xsl:variable name="real_style" select="//style:style[@style:name=$p_style]/@style:parent-style-name"/>
119      <xsl:choose>
120        <!-- Check if it is a wrong defined header (with toc attribute compare), then call header template, otherwise it s a paragraphe -->
121        <xsl:when test="not (ancestor::table:table or ancestor::text:list) and $title_style and $title_style/text:index-source-style[@text:style-name = $real_style]">
122          <xsl:call-template name="titre">
123            <xsl:with-param name="level" select="$title_style[@text:style-name = $real_style]/../@text:outline-level"/>
124          </xsl:call-template>
125        </xsl:when>
126        <xsl:when test="1 = 0"></xsl:when>
127        <xsl:otherwise>
128          <!-- Mise en forme -->
129          <xsl:call-template name="p_render"/>
130          <!-- Aplication des retours chariots selon le contexte -->
131          <xsl:choose>
132            <!-- we shouldn't add a newline for elements inside a table -->
133            <xsl:when test="ancestor::table:table-cell and not(following-sibling::text:p)"/>
134            <!-- but we would want a new between two text:p in a cell -->
135            <xsl:when test="ancestor::table:table-cell and following-sibling::text:p">
136              <xsl:text disable-output-escaping="yes">\\ </xsl:text>
137            </xsl:when>
138            <!-- we do want a single newline at the end of a list item
139            fixme : wont work correctly if a list containt §, something like liste & § -->
140            <xsl:when test="ancestor::text:list-item and following-sibling::text:p">
141              <xsl:text disable-output-escaping="yes">\\ </xsl:text>
142            </xsl:when>
143            <xsl:when test="ancestor::text:list-item">
144              <xsl:text disable-output-escaping="yes">
145</xsl:text>
146              </xsl:when>
147            <!-- and double at the end of the list
148            FIXME Trouver la bonne liaison sinon, l'intégrer ailleurs (sortie de liste par exemple)-->
149            <!--<xsl:when test="preceding-sibling::text:list"><xsl:text disable-output-escaping="yes">
150
151    </xsl:text></xsl:when>-->
152            <xsl:when test="ancestor::text:align='center'">
153              <xsl:text disable-output-escaping="yes">
154              </xsl:text>
155            </xsl:when>
156
157            <!-- Si note de bas de page, pas de retour chariot -->
158            <xsl:when test="ancestor::text:note-body"></xsl:when>
159            <xsl:otherwise>
160              <xsl:text disable-output-escaping="yes">
161
162</xsl:text>
163            </xsl:otherwise>
164          </xsl:choose>
165        </xsl:otherwise>
166      </xsl:choose>
167    </xsl:if>
168  </xsl:template>
169
170
171  <!-- Footnote -->
172  <xsl:template match="//text:note-body">
173    <xsl:text disable-output-escaping="yes">(( </xsl:text>
174    <xsl:apply-templates/>
175    <xsl:text disable-output-escaping="yes"> ))</xsl:text>
176  </xsl:template>
177  <xsl:template match="//text:note-citation"/>
178
179  <xsl:template match="//text:a">
180    <xsl:variable name="link">
181      <xsl:value-of select="@xlink:href"/>
182    </xsl:variable>
183    <xsl:variable name="link-text">
184      <xsl:value-of select="."/>
185    </xsl:variable>
186      <xsl:text disable-output-escaping="yes">[[</xsl:text>
187      <xsl:value-of select="$link"/>
188      <xsl:text disable-output-escaping="yes">|</xsl:text>
189      <xsl:value-of select="."/>
190      <xsl:text disable-output-escaping="yes">]]</xsl:text>
191  </xsl:template>
192
193  <xsl:template match="//text:list-item">
194    <xsl:variable name="level">
195      <xsl:value-of select="count(ancestor::text:list)"/>
196    </xsl:variable>
197
198    <xsl:choose>
199      <!-- Si dernier élément et vide, n'affiche rien -->
200      <xsl:when test="not(following-sibling::text:list-item) and not(text:p | text:a)"></xsl:when>
201      <xsl:otherwise>
202      <!-- Sinon, compte le nombre de listes imbriquées et affiche 2 espaces / niveau -->
203
204        <xsl:call-template name="boucle">
205          <xsl:with-param name="debut" select="1" />
206          <xsl:with-param name="fin" select="$level" />
207          <xsl:with-param name="texte" select="'  '" />
208        </xsl:call-template>
209
210        <!-- Puis affiche le symbole de liste adapté (ordonné et non ordonné) -->
211        <xsl:variable name="stylename" select="./*[1]/@text:style-name"/>
212        <xsl:variable name="listename" select="//style:style[@style:name=$stylename]/@style:list-style-name"/>
213
214        <xsl:choose>
215          <xsl:when test="parent::text:list and //text:list-style[@style:name=$listename]/text:list-level-style-bullet[@text:level=$level]"><xsl:text disable-output-escaping="yes">* </xsl:text></xsl:when>
216          <xsl:otherwise><xsl:text disable-output-escaping="yes">- </xsl:text></xsl:otherwise>
217        </xsl:choose>
218
219      </xsl:otherwise>
220    </xsl:choose>
221    <!-- Enfin, affiche le contenu -->
222    <xsl:apply-templates/>
223  </xsl:template>
224
225  <!-- Tables -->
226  <xsl:template match="//table:table">
227    <!-- Greg - Quelle utilitée ?
228    Element mediawiki supprimés
229    -->
230    <xsl:choose>
231      <xsl:when test="@table:is-sub-table='true'"><xsl:call-template name="subtable"/></xsl:when>
232      <xsl:otherwise><xsl:apply-templates/></xsl:otherwise>
233    </xsl:choose>
234    <!-- New line under a table to dissociate following table -->
235    <xsl:text disable-output-escaping="yes">
236</xsl:text>
237  </xsl:template>
238
239  <xsl:template name="subtable" match="//table:sub-table">
240    <!-- Subtable are hard to transform ! help needed ! -->
241    <xsl:if test="descendant::text:p">
242      <xsl:value-of select="$subtable_message"/>
243      <xsl:apply-templates/>
244    </xsl:if>
245  </xsl:template>
246
247  <!-- Table rows
248  Greg - Traitement d'une ligne
249  Une ligne est composée de cellule
250  Déroulé :
251   Traitement des cellules
252   Ajout d'un caractère de fin de ligne '|\n'
253  -->
254  <xsl:template match="//table:table-row">
255    <xsl:if test="descendant::text:*[text() != ''] or descendant::draw:image">
256      <xsl:apply-templates/>
257      <xsl:text disable-output-escaping="yes">|
258</xsl:text>
259    </xsl:if>
260  </xsl:template>
261
262  <!-- Table cells
263  Greg - Traitement d'une cellule
264  Déroulé :
265   Si cellule dans la zone en-tête
266     affichage en mode en-tête
267   sinon
268     affichage en mode normal
269  Traitement des fusions verticales de cellules FIXME
270  Affichage du contenu
271
272  Opérationnel :
273    Export
274    * tableau simple,
275    * tableau contenant des colonnes fusionnées
276    * tableau contenant des fusions de 2 lignes maximum (au delà, OOo créée des sous-tables complexes
277
278  ToDO : Analyser la syntaxe des tableaux ayant plus de 2 lignes fusionnées.
279  -->
280  <xsl:template match="//table:table//table:table-row/table:table-cell">
281    <xsl:choose>
282    <xsl:when test="ancestor::table:table-header-rows">
283    <xsl:text disable-output-escaping="yes">^</xsl:text>
284    </xsl:when>
285    <xsl:when test="text:p/@text:style-name = 'Table_20_Heading'">
286    <xsl:text disable-output-escaping="yes">^</xsl:text>
287    </xsl:when>
288    <xsl:otherwise>
289    <xsl:text disable-output-escaping="yes">|</xsl:text>
290    </xsl:otherwise>
291    </xsl:choose>
292    <xsl:if test="not (*[text() != ''] )"><xsl:text disable-output-escaping="yes"> </xsl:text></xsl:if>
293    <xsl:apply-templates/>
294  </xsl:template>
295
296  <!-- Handles horizontally merged cells
297  Traitement des cellules fusionnées
298  -->
299  <xsl:template match="//table:table//table:table-row/table:covered-table-cell">
300    <!-- Récupération de la position du noeud précédent -->
301    <xsl:variable name="mypos" select="position()"/>
302    <xsl:variable name="prevsib" select="../*[position() &lt; $mypos]"/>
303    <xsl:choose>
304      <xsl:when test="not($prevsib[name()= 'table:table-cell'])">
305        <xsl:text disable-output-escaping="yes">| ::: </xsl:text>
306      </xsl:when>
307      <xsl:otherwise>
308        <xsl:for-each select="$prevsib">
309          <xsl:if test="name() = 'table:table-cell' and not(following-sibling::table:table-cell)">
310            <xsl:choose>
311              <xsl:when test="$mypos &gt; 1 and @table:number-columns-spanned and position() + @table:number-columns-spanned &gt; $mypos">
312                <xsl:choose>
313                  <xsl:when test="ancestor::table:table-header-rows">
314                    <xsl:text disable-output-escaping="yes">^</xsl:text>
315                  </xsl:when>
316                  <xsl:when test="text:p/@text:style-name = 'Table_20_Heading'">
317                    <xsl:text disable-output-escaping="yes">^</xsl:text>
318                  </xsl:when>
319                  <xsl:otherwise>
320                    <xsl:text disable-output-escaping="yes">|</xsl:text>
321                  </xsl:otherwise>
322                </xsl:choose>
323              </xsl:when>
324              <xsl:otherwise>
325                <xsl:text disable-output-escaping="yes">| ::: </xsl:text>
326              </xsl:otherwise>
327            </xsl:choose>
328          </xsl:if>
329        </xsl:for-each>
330      </xsl:otherwise>
331    </xsl:choose>
332  </xsl:template>
333
334  <xsl:template name="neme-split">
335    <!-- Georges Khaznadar <georgesk@debian.org>, 2022-06-05
336
337	 renvoie la nième chaine, après séparation par le séparateur
338
339	 paramètres :
340	 ===========
341	 string : une chaîne
342	 n :      un index, 0 par défaut
343	 sep :    un séparateur, "§" par défaut
344	 depth:   la profondeur d'appel récursif, 0 par défaut
345    -->
346    <xsl:param name="string"/>
347    <xsl:param name="n" select="0"/>
348    <xsl:param name="sep" select="'§'"/>
349    <xsl:param name="depth" select="0"/>
350    <xsl:choose>
351      <xsl:when test="not (contains($string, $sep))">
352	<xsl:value-of select="$string"/>
353      </xsl:when>
354      <xsl:otherwise>
355	<xsl:variable name="prefix" select="substring-before($string, $sep)"/>
356	<xsl:variable name="suffix" select="substring-after($string, $sep)"/>
357	<xsl:choose>
358	  <xsl:when test="$n = $depth">
359	    <xsl:value-of select="$prefix"/>
360	  </xsl:when>
361	  <xsl:otherwise>
362	    <xsl:call-template name="neme-split">
363	      <xsl:with-param name="string" select="$suffix"/>
364	      <xsl:with-param name="n" select="$n"/>
365	      <xsl:with-param name="sep" select="$sep"/>
366	      <xsl:with-param name="depth" select="($depth+1)"/>
367	    </xsl:call-template>
368	  </xsl:otherwise>
369	</xsl:choose>
370      </xsl:otherwise>
371    </xsl:choose>
372  </xsl:template>
373
374  <xsl:template name="texmaths" match="//draw:g">
375    <!-- Georges Khaznadar <georgesk@debian.org>, 2022-06-05
376
377	 traite les formules entrées par le plugin TexMaths de LibreOffice
378	 pour que MathJax puisse les afficher proprement
379    -->
380    <xsl:variable name="title" select="svg:title"/>
381    <xsl:if test="$title = 'TexMaths'">
382      <xsl:text disable-output-escaping="yes">$</xsl:text>
383      <!-- troisième élément de svg:desc après séparation par les "§" -->
384      <xsl:call-template name="neme-split">
385	<xsl:with-param name="string" select="svg:desc"/>
386	<xsl:with-param name="n" select="2"/>
387	<xsl:with-param name="sep" select="'§'"/>
388      </xsl:call-template>
389      <xsl:text disable-output-escaping="yes">$</xsl:text>
390
391    </xsl:if>
392  </xsl:template>
393
394  <xsl:template match="//draw:frame">
395    <xsl:param name="cmtopx" value="37.795275591"/>
396    <xsl:text disable-output-escaping="yes" >{{</xsl:text>
397    <xsl:value-of select="draw:image/@xlink:href"/>
398    <xsl:if test="not (@svg:width = '' or @svg:height = '')">
399      <xsl:choose><!-- check cm, px, in, etc... -->
400        <xsl:when test="contains( @svg:width,'cm' )">?<xsl:value-of select="floor(number(substring-before(@svg:width,'cm')) * 37.795275591)"/><!--x<xsl:value-of select="floor(number(substring-before(@svg:height,'cm')) * 37.795275591)"/>--></xsl:when>
401        <xsl:otherwise/>
402      </xsl:choose>
403    </xsl:if>
404    <xsl:text disable-output-escaping="yes" >}}</xsl:text>
405  </xsl:template>
406
407  <xsl:template match="//draw:image">
408    <!--<xsl:text disable-output-escaping="yes" >{{</xsl:text>
409    <xsl:value-of select="substring-after(@xlink:href,'/')"/>
410    <xsl:text disable-output-escaping="yes" >}}</xsl:text>-->
411  </xsl:template>
412
413  <!-- Mise en forme des balises span et p
414  Greg - Transcription des mise en forme en ligne
415  Déroulé :
416  Mise en variables des éléments (style, contenu)
417  Si le text n'est pas vide
418    Appel de la mise en forme ouvrante
419    Intégration de contenu
420    Appel de la mise en forme sortante
421  Si le text est vide
422    On ne fait rien
423   -->
424  <xsl:template name="p_render" match="//text:span">
425    <xsl:variable name="style">
426      <xsl:value-of select="@text:style-name"/>
427    </xsl:variable>
428    <xsl:variable name="italic"><xsl:if test="//office:automatic-styles/style:style[@style:name=$style]/style:text-properties/@fo:font-style = 'italic'">//</xsl:if></xsl:variable>
429    <xsl:variable name="bold"><xsl:if test="//office:automatic-styles/style:style[@style:name=$style]/style:text-properties/@fo:font-weight = 'bold'">**</xsl:if></xsl:variable>
430    <xsl:variable name="underline"><xsl:if test="//office:automatic-styles/style:style[@style:name=$style]/style:text-properties/@style:text-underline-style = 'solid'">__</xsl:if></xsl:variable>
431    <xsl:variable name="centre"><xsl:if test="//office:automatic-styles/style:style[@style:name=$style]/style:text-properties/@fo:text-align">&lt;WRAP centeralign&gt;</xsl:if></xsl:variable>
432    <xsl:variable name="indice"><xsl:if test="contains(//office:automatic-styles/style:style[@style:name=$style]/style:text-properties/@style:text-position,'sub')">&lt;sub&gt;</xsl:if></xsl:variable>
433    <xsl:variable name="exposant"><xsl:if test="contains(//office:automatic-styles/style:style[@style:name=$style]/style:text-properties/@style:text-position,'sup')">&lt;sup&gt;</xsl:if></xsl:variable>
434    <xsl:variable name="barre"><xsl:if test="contains(//office:automatic-styles/style:style[@style:name=$style]/style:text-properties/@style:text-crossing-out,'line')">&lt;del&gt;</xsl:if></xsl:variable>
435    <xsl:variable name="text" select="."/>
436    <!-- Si le paragraphe contient du texte ou d'autres éléments -->
437    <xsl:if test="$text!='' or count(*) &gt; 0">
438      <!-- Application des mises en formes -->
439      <!-- Ouverture -->
440      <xsl:value-of select="$italic"/><xsl:value-of select="$bold"/><xsl:value-of select="$underline"/><xsl:value-of select="$centre"/><xsl:value-of select="$indice"/><xsl:value-of select="$exposant"/><xsl:value-of select="$barre"/>
441
442      <xsl:apply-templates/>
443
444      <!-- Fermeture -->
445      <xsl:if test="$barre!=''">&lt;/del&gt;</xsl:if><xsl:if test="$exposant!=''">&lt;/sup&gt;</xsl:if><xsl:if test="$indice!=''">&lt;/sub&gt;</xsl:if><xsl:if test="$centre!=''">&lt;/WRAP&gt;</xsl:if><xsl:value-of select="$underline"/><xsl:value-of select="$bold"/><xsl:value-of select="$italic"/>
446      <!-- Fin application des mises en formes -->
447    </xsl:if>
448  </xsl:template>
449
450  <!-- Display spacing #16 -->
451  <xsl:template match="//text:s">
452    <xsl:text disable-output-escaping="yes"> </xsl:text>
453  </xsl:template>
454
455
456  <!-- Boucle affichant une suite de n éléments identiques où n=fin-debut -->
457  <xsl:template name="boucle">
458    <xsl:param name="debut" select="0" />
459    <xsl:param name="fin" select="0" />
460    <xsl:param name="texte" select="'#'" />
461    <xsl:value-of select="$texte"/>
462    <xsl:if test="$debut &lt; $fin">
463    <xsl:call-template name="boucle">
464      <xsl:with-param name="debut" select="($debut)+1" />
465      <xsl:with-param name="fin" select="$fin" />
466      <xsl:with-param name="texte" select="$texte" />
467    </xsl:call-template>
468    </xsl:if></xsl:template>
469
470</xsl:stylesheet>
471