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(*) > 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() < $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 > 1 and @table:number-columns-spanned and position() + @table:number-columns-spanned > $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"><WRAP centeralign></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')"><sub></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')"><sup></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')"><del></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(*) > 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!=''"></del></xsl:if><xsl:if test="$exposant!=''"></sup></xsl:if><xsl:if test="$indice!=''"></sub></xsl:if><xsl:if test="$centre!=''"></WRAP></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 < $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