1 <?xml version=
"1.0" encoding=
"utf-8"?>
2 <!DOCTYPE xsl:stylesheet [
4 <!-- "xml:space='preserve'" is needed for use with libxslt -->
5 <!-- "xmlns:xsl='http://www.w3.org/1999/XSL/Transform'" is needed for
7 <!-- Used to create a blank line -->
8 <!ENTITY tCR
"<xsl:text xmlns:xsl='http://www.w3.org/1999/XSL/Transform' xml:space='preserve'>&CR;</xsl:text>">
9 <!-- Used when the line before must be ended -->
10 <!ENTITY tEOL
"<xsl:text xmlns:xsl='http://www.w3.org/1999/XSL/Transform' xml:space='preserve'>&CR;</xsl:text>">
11 <!ENTITY tSP
"<xsl:text xmlns:xsl='http://www.w3.org/1999/XSL/Transform' xml:space='preserve'> </xsl:text>">
15 Copyright (C) 2005, 2006 Stefan Merten, David Priest
16 Copyright (C) 2009, 2010, 2011 Stefan Merten
18 xml2rst.xsl is free software; you can redistribute it and/or modify
19 it under the terms of the GNU General Public License as published
20 by the Free Software Foundation; either version 2 of the License,
21 or (at your option) any later version.
23 This program is distributed in the hope that it will be useful,
24 but WITHOUT ANY WARRANTY; without even the implied warranty of
25 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
26 General Public License for more details.
28 You should have received a copy of the GNU General Public License
29 along with this program; if not, write to the Free Software
30 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
34 <!-- ********************************************************************** -->
35 <!-- ********************************************************************** -->
37 <!-- These elements in the DTD need support:
39 - ``colspec`` has attribute "stub %yesorno; #IMPLIED"
41 - ``document`` has attribute "title CDATA #IMPLIED"
43 Probably rendered by the `.. title::` directive
48 Set namespace extensions. These are used as [shortname]:[tag] throughout the
50 xsl: eXtensible Stylesheet Language
51 u: user extensions (indicates utility 'call-template' routines defined in
53 data: Data elements used by the stylesheet
57 xmlns:
xsl=
"http://www.w3.org/1999/XSL/Transform"
60 exclude-result-prefixes=
"data"
61 xmlns:
str=
"http://exslt.org/strings"
62 xmlns:
dyn=
"http://exslt.org/dynamic"
63 xmlns:
math=
"http://exslt.org/math"
64 extension-element-prefixes=
"str dyn math">
66 <!-- xmlns:regexp="http://exslt.org/regular-expressions" not supported :-( -->
70 omit-xml-declaration=
"yes"
73 <!-- ******************************************************************** -->
74 <!-- ******************************************************************** -->
76 <!-- Parameter to configure title markup; see manual page for description -->
79 select=
"'o=o-u=u-u~u`u,u.'"/>
81 <!-- Parameter for folding long lines; see manual page for description -->
86 <!-- ******************************************************************** -->
87 <!-- ******************************************************************** -->
94 name=
"structural_elements"
95 select=
"'*document*section*topic*sidebar*'"/>
98 name=
"structural_subelements"
99 select=
"'*title*subtitle*docinfo*decoration*transition*'"/>
102 name=
"bibliographic_elements"
103 select=
"'*address*author*authors*contact*copyright*date*field*organization*revision*status*version*'"/>
106 name=
"decorative_elements"
107 select=
"'*footer*header*'"/>
110 name=
"simple_body_elements_no_substitution"
111 select=
"'*comment*doctest_block*image*literal_block*paragraph*pending*raw*rubric*target*'"/>
114 name=
"folding_elements"
115 select=
"concat('*comment*paragraph*rubric*attribution*caption*line*', substring-after($bibliographic_elements, '*'))"/>
118 name=
"simple_body_elements"
119 select=
"concat($simple_body_elements_no_substitution, 'substitution_definition*')"/>
122 name=
"compound_body_elements"
123 select=
"'*admonition*attention*block_quote*bullet_list*caution*citation*compound*danger*definition_list*enumerated_list*error*field_list*figure*footnote*hint*important*line_block*note*option_list*system_message*table*tip*warning*container*'"/>
127 select=
"concat($simple_body_elements, substring-after($compound_body_elements, '*'))"/>
131 select=
"'*admonition*attention*caution*danger*error*hint*important*note*tip*warning*'"/>
134 name=
"simple_body_subelements"
135 select=
"'*attribution*caption*classifier*colspec*field_name*label*line*option_argument*option_string*term*'"/>
138 name=
"compound_body_subelements"
139 select=
"'*definition*definition_list_item*description*entry*field*field_body*legend*list_item*option*option_group*option_list_item*row*tbody*tgroup*thead*'"/>
142 name=
"inline_elements"
143 select=
"'*abbreviation*acronym*citation_reference*emphasis*footnote_reference*generated*image*inline*literal*problematic*reference*strong*subscript*substitution_reference*superscript*target*title_reference*raw*'"/>
146 name=
"inline_containers"
147 select=
"concat($simple_body_elements_no_substitution, substring-after($inline_elements, '*'))"/>
151 select=
"'*admonition*attention*caution*comment*danger*error*footnote*hint*important*note*tip*warning*image*figure*topic*sidebar*rubric*meta*raw*citation*compound*substitution_definition*container*'"/>
154 name=
"titled_elements"
155 select=
"'*sidebar*topic*admonition*'"/>
159 select=
"concat($structural_elements, substring-after($structural_subelements, '*'), substring-after($body_elements, '*'))"/>
162 name=
"adornment_characters"
163 select=
"concat($apos, '!"#$%&()*+,-./:;<=>?@[\]^_`{|}~')"/>
165 <!-- ******************************************************************** -->
166 <!-- ******************************************************************** -->
169 Content Model: ((title, subtitle?)?, docinfo?, decoration?,
172 Attributes: The document element contains only the common attributes: ids,
173 names, dupnames, source, and classes.
175 Depending on the source of the data and the stage of processing, the
176 "document" may not initially contain a "title". A document title is not
177 directly representable in reStructuredText. Instead, a lone top-level section
178 may have its title promoted to become the document title, and similarly for a
179 lone second-level (sub)section's title to become the document subtitle. The
180 "docinfo" may be transformed from an initial field_list, and "decoration" is
181 usually constructed programmatically.
183 <!-- == structural_element -->
187 test=
"//generated[@classes = 'sectnum']">
188 <xsl:text>.. section-numbering::
</xsl:text>
193 name=
"u:outputClass">
198 <xsl:apply-templates/>
201 <!-- ******************************************************************** -->
204 Content Model: (title, %structure.model;)
205 Attributes: The section element contains only the common attributes: ids,
206 names, dupnames, source, and classes.
208 <!-- == structural_element -->
212 name=
"u:outputClass"/>
215 <xsl:apply-templates/>
218 <!-- == structural_element -->
220 match=
"section[@classes = 'system-messages']"/>
221 <!-- Ignore system messages completely -->
222 <!-- This should be really in `generated' -->
224 <!-- ******************************************************************** -->
227 Content Model: (title, subtitle?, (%body.elements;)+)
228 Attributes: The sidebar element contains only the common attributes: ids,
229 names, dupnames, source, and classes.
231 <!-- == structural_element == directive -->
236 <xsl:text>.. sidebar::
</xsl:text>
246 select=
"'subtitle'"/>
252 select=
"ancestor-or-self::*"/>
257 <!-- Always blank line after parameter block -->
260 select=
"*[not(self::title) and not(self::subtitle)]"/>
263 <!-- ******************************************************************** -->
266 Content Model: (title?, (%body.elements;)+)
267 Attributes: The topic element contains only the common attributes: ids,
268 names, dupnames, source, and classes.
270 <!-- == structural_element == directive -->
275 <xsl:text>.. topic::
</xsl:text>
282 select=
"*[not(self::title)]"/>
285 <!-- == structural_element == directive -->
287 match=
"topic[starts-with(@classes, 'contents')]">
290 <xsl:text>.. contents::
</xsl:text>
298 select=
"@*[name() != 'ids' and name() != 'names' and name() != 'classes']"/>
302 select=
"substring-before(@classes, ' local')"/>
304 name=
"realClassesLocal"
305 select=
"normalize-space(substring-after(@classes, 'contents'))"/>
307 name=
"realClassesNode">
312 select=
"normalize-space(substring-before($realClassesLocal, 'local'))"/>
316 select=
"$realClassesLocal"/>
322 select=
"string($realClassesNode)"/>
335 select=
"ancestor-or-self::*"/>
347 select=
"$realClasses"/>
350 select=
"ancestor-or-self::*"/>
353 <!-- Autogenerated content is discarded -->
357 <!-- == structural_element == directive -->
359 match=
"topic[@classes='dedication' or @classes='abstract']">
362 <xsl:text>:
</xsl:text>
365 <xsl:text>:
</xsl:text>
368 select=
"*[not(self::title)]"/>
371 <!-- ******************************************************************** -->
374 Content Model: (title, (%body.elements;)+)
375 Attributes: The admonition element contains only the common attributes:
376 ids, names, dupnames, source, and classes.
378 <!-- == compound_body_element == directive -->
383 <xsl:text>.. admonition::
</xsl:text>
391 select=
"@*[name() != 'classes' or not(starts-with(., 'admonition-'))]"/>
396 select=
"*[not(self::title)]"/>
399 <!-- ******************************************************************** -->
402 Content Model: (%body.elements;)+
403 Attributes: The note element contains only the common attributes: ids,
404 names, dupnames, source, and classes.
406 <!-- == compound_body_element == directive -->
408 match=
"attention | caution | danger | error | hint | important | note | tip | warning">
410 name=
"u:outputClass"/>
413 <xsl:text>..
</xsl:text>
416 <xsl:text>::
</xsl:text>
421 select=
"@*[name() != 'classes']"/>
423 <xsl:apply-templates/>
426 <!-- ******************************************************************** -->
429 Content Model: (header?, footer?)
430 Attributes: The decoration element contains only the common attributes:
431 ids, names, dupnames, source, and classes.
433 Although the content model doesn't specifically require contents, no empty
434 decoration elements are ever created.
436 <!-- == structural_subelement -->
438 match=
"//document/decoration">
439 <xsl:apply-templates/>
442 <!-- TODO To be rendered as `.. header::` directive -->
443 <!-- == decorative_element -->
445 match=
"//document/decoration/header">
446 <xsl:apply-templates/>
449 <!-- TODO To be rendered as `.. footer::` directive -->
450 <!-- == decorative_element -->
452 match=
"//document/decoration/footer">
453 <xsl:apply-templates/>
456 <!-- ******************************************************************** -->
459 Content Model: (%bibliographic.elements;)+
460 Attributes: The docinfo element contains only the common attributes: ids,
461 names, dupnames, source, and classes.
463 <!-- == structural_subelement -->
467 name=
"u:outputClass"/>
470 <xsl:apply-templates/>
475 <!-- ******************************************************************** -->
478 Content Model: ((author, organization?, address?, contact?)+)
479 Attributes: The authors element contains only the common attributes: ids,
480 names, dupnames, source, and classes.
482 In reStructuredText, multiple author's names are separated with semicolons
483 (";") or commas (","); semicolons take precedence. There is currently no way
484 to represent the author's organization, address, or contact in a
485 reStructuredText "Authors" field.
487 <!-- == bibliographic_element == folding_element -->
489 match=
"docinfo/authors">
491 name=
"u:outputFolding">
494 <xsl:text>:
</xsl:text>
497 <xsl:text>:
</xsl:text>
503 Content Model: %text.model;
504 Attributes: All docinfo elements contains the common attributes (ids,
505 names, dupnames, source, and classes)
506 Some docinfo elements also have xml:space.
509 match=
"docinfo/authors/*">
510 <xsl:apply-templates/>
511 <!-- no semicolon after final author -->
513 test=
"generate-id(current()) != generate-id(../*[last()])">
514 <xsl:text>;
</xsl:text>
519 Content Model: (field_name, field_body)
520 Attributes: The field element contains only the common attributes: ids,
521 names, dupnames, source, and classes.
523 <!-- == bibliographic_element -->
525 match=
"docinfo/field">
526 <!-- contents handled by ordinary field lists -->
527 <xsl:apply-templates/>
528 <!-- Supply an EOL because following elements do not recognize this -->
533 Content Model: %text.model;
534 Attributes: All docinfo elements contains the common attributes (ids,
535 names, dupnames, source, and classes)
536 Some docinfo elements also have xml:space.
538 <!-- == bibliographic_element == folding_element -->
540 match=
"docinfo/*[name()!='authors' and name()!='field']">
542 name=
"u:outputFolding">
545 <xsl:text>:
</xsl:text>
548 <xsl:text>:
</xsl:text>
553 <!-- ******************************************************************** -->
557 Attributes: The transition element contains only the common attributes:
558 ids, names, dupnames, source, and classes.
560 <!-- == structural_subelement -->
564 name=
"u:outputClass"/>
565 &tCR; <!-- req: blank line before -->
566 <xsl:text>-----
</xsl:text>
568 <!-- Add a required blank line after unless class follows immediately -->
570 test=
"not(following-sibling::*[1]/@classes)">
575 <!-- ******************************************************************** -->
576 <!-- ******************************************************************** -->
579 IFF there is a /document/title element, it is the publication's title. All
580 other titles will appear within sections.
582 Content Model: %text.model;
583 Attributes: The title element contains the common attributes (ids, names,
584 dupnames, source, and classes), plus refid and auto.
585 refid is used as a backlink to a table of contents entry.
586 auto is used to indicate (with value "1") that the title has been
587 numbered automatically.
589 <!-- == structural_subelement -->
591 match=
"//document/title">
593 name=
"u:outputClass"/>
596 <!-- Catch the title text as it is rendered so its length can be
598 <xsl:apply-templates/>
602 select=
"normalize-space($textWS)"/>
605 select=
"string-length($text)"/>
629 <!-- ******************************************************************** -->
632 Title Underlines are defined by their position within the tree.
634 Content Model: %text.model;
635 Attributes: The title element contains the common attributes (ids, names,
636 dupnames, source, and classes), plus refid and auto.
637 refid is used as a backlink to a table of contents entry.
638 auto is used to indicate (with value "1") that the title has been
639 numbered automatically.
641 <!-- == structural_subelement -->
643 match=
"section/title">
645 name=
"u:outputClass"/>
648 <!-- catch the title text as it is rendered -->
649 <xsl:apply-templates/>
653 select=
"normalize-space($textWS)"/>
656 select=
"string-length($text)"/>
659 select=
"count(ancestor::section)"/>
667 select=
"$depth + 2"/>
679 select=
"$depth + 2"/>
681 <!-- Add a blank line after unless structure follows immediately -->
683 test=
"not(contains(concat($structural_elements, $compound_body_elements), concat('*', name(following-sibling::*[1]), '*')) or following-sibling::*[1]/@classes)">
688 <!-- ******************************************************************** -->
691 Content Model: %text.model;
692 Attributes: The title element contains the common attributes (ids, names,
693 dupnames, source, and classes), plus refid and auto.
694 refid is used as a backlink to a table of contents entry.
695 auto is used to indicate (with value "1") that the title has been
696 numbered automatically.
698 <!-- == structural_subelement -->
702 name=
"u:outputClass">
704 name=
"alreadyBlanked"
707 <!-- blank line provided by parent -->
708 <xsl:apply-templates/>
709 <!-- no EOL: provided by parent -->
712 <!-- ******************************************************************** -->
715 IFF there is a /document/title element, it is the publication's title. All
716 other titles will appear within sections.
718 Content Model: %text.model;
719 Attributes: The subtitle element contains only the common attributes:
720 ids, names, dupnames, source, and classes.
722 <!-- == structural_subelement -->
724 match=
"//document/subtitle">
726 name=
"u:outputClass"/>
729 <!-- Catch the title text as it is rendered -->
730 <xsl:apply-templates/>
734 select=
"normalize-space($textWS)"/>
737 select=
"string-length($text)"/>
739 <!-- always a blank line above -->
764 <!-- ******************************************************************** -->
767 Content Model: %text.model;
768 Attributes: The subtitle element contains only the common attributes: ids,
769 names, dupnames, source, and classes.
771 <!-- == structural_subelement -->
773 match=
"sidebar/subtitle">
775 name=
"u:outputClass"/>
778 <xsl:apply-templates/>
783 <!-- ******************************************************************** -->
784 <!-- ******************************************************************** -->
787 Content Model: %text.model;
788 Attributes: The comment element contains only the common attributes: ids,
789 names, dupnames, source, and classes.
791 <!-- == simple_body_element == folding_element == directive -->
797 name=
"u:outputFolding">
800 <xsl:text>..
</xsl:text>
805 <!-- ******************************************************************** -->
808 Content Model: %text.model;
809 Attributes: The doctest_block element contains the common attributes (ids,
810 names, dupnames, source, and classes), plus xml:space.
812 <!-- == simple_body_element -->
814 match=
"doctest_block">
816 name=
"u:outputClass"/>
819 <xsl:apply-templates/>
823 <!-- ******************************************************************** -->
825 <!-- An image element can have various roles; they are all covered here -->
826 <!-- == simple_body_element == inline_element == directive -->
831 test=
"contains($inline_containers, concat('*', name(..), '*')) and @alt">
832 <!-- An inline image with an `@alt' - must be a substitution
834 <xsl:text>|
</xsl:text>
835 <!-- Original text is lost - use what we have -->
838 <xsl:text>|
</xsl:text>
843 test=
"not(parent::figure)">
845 test=
"not(parent::substitution_definition)">
848 <xsl:text>..
</xsl:text>
850 <xsl:text>image::
</xsl:text>
857 test=
"parent::figure">
858 <!-- `@classes' is special because it is in the parent -->
865 select=
"'figclass'"/>
868 select=
"../@classes"/>
871 select=
"ancestor::*"/>
874 <!-- `@align' is special because it is in the parent -->
887 select=
"ancestor::*"/>
892 <!-- `figure' would add one level of indentation -->
895 select=
"ancestor::*"/>
899 test=
"parent::substitution_definition">
902 <!-- `@alt' only for the real images -->
905 select=
"@*[name() != 'alt']"/>
913 select=
"@*[name() != 'ids' and name() != 'names']"/>
918 test=
"parent::reference">
919 <!-- A clickable image -->
930 <!-- An internal link -->
932 name=
"u:inlineReference">
939 <!-- An external link -->
941 select=
"../@refuri"/>
947 select=
"ancestor-or-self::*"/>
950 <!-- Always blank line after parameter block -->
956 <!-- ******************************************************************** -->
959 Content Model: (line_block | line)+
960 Attributes: The line_block element contains the common attributes (ids,
961 names, dupnames, source, and classes), plus xml:space.
963 <!-- == compound_body_element -->
967 name=
"u:outputClass"/>
970 select=
"name(..) = 'line_block'"/>
972 test=
"not($isEmbedded)">
976 <xsl:apply-templates/>
979 <!-- ******************************************************************** -->
982 Content Model: %text.model;
983 Attributes: The line element contains the common attributes (ids,
984 names, dupnames, source, and classes).
986 <!-- == simple_body_subelement == folding_element -->
990 name=
"u:outputClass"/>
1001 <!-- Only for non-empty lines -->
1003 name=
"lineBlockIndent">
1004 <!-- Very special indendation for nested `line_block's -->
1006 select=
"ancestor::line_block[position() > 1]">
1008 select=
"str:padding(4)"/>
1012 name=
"u:outputFolding">
1015 <xsl:text>|
</xsl:text>
1017 select=
"$lineBlockIndent"/>
1021 select=
"concat($indent, ' ', $lineBlockIndent)"/>
1022 </xsl:call-template>
1025 <xsl:text>|
</xsl:text>
1031 <!-- ******************************************************************** -->
1034 Content Model: %text.model;
1035 Attributes: The literal_block element contains the common attributes (ids,
1036 names, dupnames, source, and classes), plus xml:space.
1038 <!-- == simple_body_element == directive -->
1040 match=
"literal_block">
1043 test=
".//*[contains($inline_elements, concat('*', name(), '*'))]">
1044 <!-- If it contains inline elements this is a parsed-literal -->
1047 <xsl:text>.. parsed-literal::
</xsl:text>
1055 name=
"u:outputClass"/>
1056 <!-- TODO Support for the (fully) minimized style would be nice but
1057 is difficult to accomplish because there is a linefeed
1058 already when we arrive here :-( -->
1061 <xsl:text>::
</xsl:text>
1067 name=
"isQuotedLiteral">
1069 name=
"u:isQuotedLiteral"/>
1071 <!-- Indent correctly depending on quoted literal or not -->
1074 test=
"string-length($isQuotedLiteral)">
1079 select=
"ancestor::*"/>
1080 </xsl:call-template>
1081 <xsl:apply-templates
1082 mode=
"quotedLiteral"/>
1089 select=
"ancestor-or-self::*"/>
1090 </xsl:call-template>
1091 <xsl:apply-templates/>
1097 <!-- Indent a text of a quoted literal containing line feeds correctly -->
1100 mode=
"quotedLiteral">
1109 select=
"ancestor::*[position() > 1]"/>
1110 </xsl:call-template>
1112 </xsl:call-template>
1115 <!-- Determine whether `$text' is a quoted literal and return the quote
1118 name=
"u:isQuotedLiteral">
1124 select=
"substring($text, 1, 1)"/>
1126 test=
"contains($adornment_characters, $quote) and substring($text, 1, 1) = $quote">
1127 <!-- Given quote is an adornment character and first character is this
1131 test=
"contains($text, '
')">
1132 <!-- Test the remaining lines -->
1134 name=
"u:isQuotedLiteral">
1137 select=
"substring-after($text, '
')"/>
1141 </xsl:call-template>
1144 <!-- No more lines to test so this is a quoted literal -->
1152 <!-- ******************************************************************** -->
1155 Content Model: %text.model;
1156 Attributes: The paragraph element contains only the common attributes:
1157 ids, names, dupnames, source, and classes.
1159 <!-- == simple_body_element == folding_element -->
1164 select=
"preceding-sibling::*[1]"/>
1165 <!-- Do indent except first element in some compound elements -->
1168 select=
"($previous or not(parent::list_item or parent::field_body or contains($admonitions, concat('*', name(..), '*')))) and name($previous) != 'label'"/>
1169 <!-- Blank line in front if following a body element, except first
1170 elements in some compound elements -->
1173 select=
"($previous or not(parent::list_item or ../parent::option_list_item or parent::field_body or parent::document or contains($admonitions, concat('*', name(..), '*')))) and (not($previous) or contains($body_elements, concat('*', name($previous), '*')) or name($previous) = 'title' and contains($titled_elements, concat('*', name(..), '*')) or name($previous) = 'docinfo')"/>
1179 test=
"$needsIndent">
1185 <!-- This paragraph has a classes attribute - always needs newline and
1188 name=
"u:outputClass">
1190 name=
"alreadyBlanked"
1191 select=
"$needsBlank"/>
1193 name=
"alreadyIndented"
1194 select=
"$needsIndent"/>
1195 </xsl:call-template>
1200 name=
"u:outputFolding"/>
1203 <!-- ******************************************************************** -->
1205 <!-- == simple_body_element -->
1209 name=
"u:notSupported"/>
1212 <!-- ******************************************************************** -->
1214 <!-- == simple_body_element == inline_element == directive -->
1219 test=
"contains($inline_containers, concat('*', name(..), '*'))">
1220 <!-- Used as a custom role -->
1221 <!-- TODO `role' directives must be generated for user-defined raw
1223 <!-- The name of the custom role is not contained in the input -->
1224 <xsl:text>:RAW-ROLE:`
</xsl:text>
1225 <xsl:apply-templates/>
1226 <xsl:text>`
</xsl:text>
1229 <!-- A directive -->
1231 name=
"u:outputClass"/>
1234 <xsl:text>.. raw::
</xsl:text>
1242 select=
"@*[name() != 'format' and name() != 'classes']"/>
1243 </xsl:call-template>
1249 select=
"ancestor-or-self::*"/>
1250 </xsl:call-template>
1251 <xsl:apply-templates/>
1257 <!-- ******************************************************************** -->
1259 <!-- == simple_body_element == folding_element == directive -->
1265 name=
"u:outputFolding">
1268 <xsl:text>.. rubric::
</xsl:text>
1270 </xsl:call-template>
1275 <!-- ******************************************************************** -->
1277 <!-- == compound_body_element == directive -->
1282 <xsl:text>.. compound::
</xsl:text>
1286 <xsl:apply-templates/>
1289 <!-- ******************************************************************** -->
1291 <!-- == compound_body_element == directive -->
1296 <xsl:text>.. container::
</xsl:text>
1304 <xsl:apply-templates/>
1307 <!-- ******************************************************************** -->
1309 <!-- == simple_body_element == directive -->
1311 match=
"substitution_definition">
1312 <!-- More than one child or not a directive is a replacement text -->
1315 select=
"not(* and count(node()) = 1 and contains($directives, concat('*', name(*[1]), '*')))"/>
1320 <xsl:text>.. |
</xsl:text>
1322 name=
"u:outputNames"/>
1323 <xsl:text>|
</xsl:text>
1328 <!-- TODO Substitution references for replace can not be found because
1329 they are not marked as such; embedding them in `generated'
1332 name=
"u:outputFolding">
1337 <xsl:text>replace::
</xsl:text>
1339 </xsl:call-template>
1344 <xsl:apply-templates/>
1349 <!-- ******************************************************************** -->
1352 Content Model: ((%body.elements;)+, attribution?)
1353 Attributes: The block_quote element contains only the common attributes:
1354 ids, names, dupnames, source, and classes.
1356 <!-- == compound_body_element -->
1358 match=
"block_quote">
1360 test=
"@classes = 'epigraph' or @classes = 'highlights' or @classes = 'pull-quote'">
1363 <xsl:text>..
</xsl:text>
1366 <xsl:text>::
</xsl:text>
1371 <xsl:apply-templates/>
1374 <!-- ******************************************************************** -->
1376 <!-- == simple_body_subelement == folding_element -->
1378 match=
"attribution">
1380 name=
"u:outputClass"/>
1381 <!-- blank line between quote and attribution -->
1386 name=
"u:outputFolding">
1389 <xsl:text>--
</xsl:text>
1391 </xsl:call-template>
1394 <!-- ******************************************************************** -->
1396 <!-- == compound_body_element == directive -->
1400 name=
"u:outputClass"/>
1403 <xsl:text>.. [
</xsl:text>
1406 <xsl:text>]
</xsl:text>
1407 <xsl:apply-templates
1408 select=
"*[not(self::label)]"/>
1411 <!-- == simple_body_subelement -->
1413 match=
"citation/label">
1414 <xsl:apply-templates/>
1417 <!-- ******************************************************************** -->
1419 <!-- == compound_body_element == directive -->
1424 <xsl:text>.. figure::
</xsl:text>
1425 <xsl:apply-templates/>
1428 <!-- ******************************************************************** -->
1430 <!-- == simple_body_subelement == folding_element -->
1436 name=
"u:outputFolding"/>
1439 <!-- ******************************************************************** -->
1441 <!-- == compound_body_subelement -->
1444 <xsl:apply-templates/>
1447 <!-- ******************************************************************** -->
1449 <!-- TODO Footnotes should continue on line of definition -->
1451 <!-- user-numbered footnotes lack @auto -->
1452 <!-- == compound_body_element == directive -->
1454 match=
"footnote[not(@auto)]">
1456 name=
"u:outputClass"/>
1459 <xsl:text>.. [
</xsl:text>
1460 <xsl:apply-templates
1462 <xsl:text>]
</xsl:text>
1463 <xsl:apply-templates
1464 select=
"*[not(self::label)]"/>
1467 <!-- autonumbered footnotes have @auto -->
1468 <!-- if the target footnote_reference@names matches its label, it was not a
1469 numbered-name footnote -->
1470 <!-- == compound_body_element == directive -->
1472 match=
"footnote[@auto='1']">
1474 name=
"u:outputClass"/>
1477 <xsl:text>.. [#
</xsl:text>
1479 test=
"@names = @ids">
1481 name=
"u:outputNames"/>
1483 <xsl:text>]
</xsl:text>
1484 <xsl:apply-templates
1485 select=
"*[not(self::label)]"/>
1488 <!-- autosymboled footnotes have @auto -->
1489 <!-- == compound_body_element == directive -->
1491 match=
"footnote[@auto='*']">
1493 name=
"u:outputClass"/>
1496 <xsl:text>.. [*]
</xsl:text>
1497 <xsl:apply-templates
1498 select=
"*[not(self::label)]"/>
1501 <!-- == compound_body_element == directive -->
1503 match=
"footnote[starts-with(@names, 'TARGET_NOTE:\ ')]">
1504 <!-- This is not a footnote but a hint for a directive -->
1506 test=
"generate-id(//footnote[starts-with(@names, 'TARGET_NOTE:\ ')][1]) = generate-id(.)">
1507 <!-- Only for the first one -->
1510 <!-- TODO May have a `classes` attribute -->
1511 <xsl:text>.. target-notes::
</xsl:text>
1516 <!-- == simple_body_subelement -->
1518 match=
"footnote/label">
1519 <xsl:apply-templates/>
1522 <!-- ******************************************************************** -->
1525 Content Model: (list_item +)
1526 Attributes: The bullet_list element contains the common attributes (ids,
1527 names, dupnames, source, and classes), plus bullet.
1528 bullet is used to record the style of bullet from the input data.
1529 In documents processed from reStructuredText, it contains one of "-",
1530 "+", or "*". It may be ignored in processing.
1532 <!-- == compound_body_element -->
1534 match=
"bullet_list">
1536 name=
"u:outputClass"/>
1537 <xsl:apply-templates
1538 mode=
"bullet_list"/>
1541 <!-- ******************************************************************** -->
1544 Content Model: (definition_list_item +)
1545 Attributes: The definition_list element contains only the common
1546 attributes: ids, names, dupnames, source, and classes.
1548 <!-- == compound_body_element -->
1550 match=
"definition_list">
1552 name=
"u:outputClass"/>
1553 <xsl:apply-templates/>
1556 <!-- ******************************************************************** -->
1559 Content Model: (term, classifier?, definition)
1560 Attributes: The definition_list_item element contains only the common
1561 attributes: ids, names, dupnames, source, and classes.
1563 <!-- == compound_body_subelement -->
1565 match=
"definition_list_item">
1567 name=
"u:outputClass"/>
1570 <xsl:apply-templates/>
1573 <!-- ******************************************************************** -->
1576 Content Model: %text.model;
1577 Attributes: The term element contains only the common attributes: ids,
1578 names, dupnames, source, and classes.
1580 <!-- == simple_body_subelement -->
1583 <xsl:apply-templates/>
1586 <!-- ******************************************************************** -->
1589 Content Model: %text.model;
1590 Attributes: The classifier element contains only the common attributes:
1591 ids, names, dupnames, source, and classes.
1593 <!-- == simple_body_subelement -->
1596 <xsl:text> :
</xsl:text>
1597 <xsl:apply-templates/>
1600 <!-- ******************************************************************** -->
1603 Content Model: (%body.elements;)+
1604 Attributes: The definition element contains only the common attributes:
1605 ids, names, dupnames, source, and classes.
1607 <!-- == compound_body_subelement -->
1611 name=
"u:outputClass"/>
1612 <xsl:apply-templates/>
1615 <!-- ******************************************************************** -->
1618 Content Model: (list_item +)
1619 Attributes: The enumerated_list element contains the common attributes
1620 (ids, names, dupnames, source, and classes), plus enumtype, prefix, suffix, and
1622 enumtype is used to record the intended enumeration sequence, one
1623 of "arabic" (1, 2, 3, ...), "loweralpha" (a, b, c, ..., z), "upperalpha" (A,
1624 B, C, ..., Z), "lowerroman" (i, ii, iii, iv, ..., mmmmcmxcix [4999]), or
1625 "upperroman" (I, II, III, IV, ..., MMMMCMXCIX [4999]).
1626 prefix stores the formatting characters used before the enumerator. In
1627 documents originating from reStructuredText data, it will contain either ""
1628 (empty string) or "(" (left parenthesis). It may or may not affect
1630 suffix stores the formatting characters used after the enumerator. In
1631 documents originating from reStructuredText data, it will contain either "."
1632 (period) or ")" (right parenthesis). Depending on the capabilities of the
1633 output format, this attribute may or may not affect processing.
1634 start contains the ordinal value of the first item in the list, in
1635 decimal. For lists beginning at value 1 ("1", "a", "A", "i", or "I"), this
1636 attribute may be omitted.
1638 <!-- == compound_body_element -->
1640 match=
"enumerated_list">
1642 name=
"u:outputClass"/>
1643 <xsl:apply-templates
1644 mode=
"enumerated_list"/>
1647 <!-- ******************************************************************** -->
1650 Content Model: (field +)
1651 Attributes: The field_list element contains only the common attributes:
1652 ids, names, dupnames, source, and classes.
1654 <!-- == compound_body_element -->
1658 name=
"u:outputClass"/>
1659 <xsl:apply-templates/>
1662 <!-- ******************************************************************** -->
1665 Content Model: (field_name, field_body)
1666 Attributes: The field element contains only the common attributes: ids,
1667 names, dupnames, source, and classes.
1669 <!-- == compound_body_subelement -->
1673 name=
"u:outputClass"/>
1676 <xsl:apply-templates/>
1679 <!-- ********************************************************************** -->
1682 Content Model: %text.model;
1683 Attributes: The field_name element contains only the common attributes:
1684 ids, names, dupnames, source, and classes.
1686 <!-- == simple_body_subelement -->
1689 <xsl:text>:
</xsl:text>
1690 <xsl:apply-templates/>
1691 <xsl:text>:
</xsl:text>
1692 <!-- no EOL: field_body starts on same line -->
1695 <!-- ******************************************************************** -->
1698 Content Model: (%body.elements;)*
1699 Attributes: The field_body element contains only the common attributes:
1700 ids, names, dupnames, source, and classes.
1702 <!-- == compound_body_subelement -->
1706 name=
"u:outputClass"/>
1707 <xsl:apply-templates/>
1710 <!-- ******************************************************************** -->
1713 Content Model: (option_list_item +)
1714 Attributes: The option_list element contains only the common attributes:
1715 ids, names, dupnames, source, and classes.
1717 <!-- == compound_body_element -->
1719 match=
"option_list">
1721 name=
"u:outputClass"/>
1724 <xsl:apply-templates/>
1727 <!-- ******************************************************************** -->
1730 Content Model: (option_group, description)
1731 Attributes: The option_list_item element contains only the common
1732 attributes: ids, names, dupnames, source, and classes.
1734 <!-- == compound_body_subelement -->
1736 match=
"option_list_item">
1738 name=
"u:outputClass"/>
1741 <xsl:apply-templates/>
1744 <!-- ******************************************************************** -->
1747 Content Model: (option_group, description)
1748 Attributes: The option_group element contains only the common attributes:
1749 ids, names, dupnames, source, and classes.
1751 <!-- == compound_body_subelement -->
1753 match=
"option_group">
1754 <xsl:apply-templates/>
1758 <!-- ******************************************************************** -->
1761 Content Model: (option_string, option_argument *)
1762 Attributes: The option element contains only the common attributes: ids,
1763 names, dupnames, source, and classes.
1765 <!-- == compound_body_subelement -->
1769 name=
"u:outputClass"/>
1770 <xsl:apply-templates/>
1772 test=
"generate-id(current()) != generate-id(../*[last()])">
1773 <!-- No comma after final option -->
1774 <xsl:text>,
</xsl:text>
1776 <!-- no EOL: description on same line -->
1779 <!-- ******************************************************************** -->
1782 Content Model: (#PCDATA)
1783 Attributes: The option_string element contains only the common attributes:
1784 ids, names, dupnames, source, and classes.
1786 <!-- == simple_body_subelement -->
1788 match=
"option_string">
1789 <xsl:apply-templates/>
1792 <!-- ******************************************************************** -->
1795 Content Model: (#PCDATA)
1796 Attributes: The option_argument element contains the common attributes
1797 (ids, names, dupnames, source, and classes), plus delimiter.
1798 delimiter contains the text preceding the option_argument:
1799 either the text separating it from the option_string (typically
1801 or the text between option arguments (typically either "," or " ").
1803 <!-- == simple_body_subelement -->
1805 match=
"option_argument">
1807 select=
"@delimiter"/>
1808 <xsl:apply-templates/>
1811 <!-- ******************************************************************** -->
1814 Content Model: (%body.elements;)+
1815 Attributes: The description element contains only the common attributes:
1816 ids, names, dupnames, source, and classes.
1818 <!-- == compound_body_subelement -->
1820 match=
"description">
1822 name=
"u:outputClass"/>
1823 <xsl:apply-templates/>
1827 <!-- ******************************************************************** -->
1830 Content Model: (%body.elements;)+
1831 Attributes: The list_item element contains only the common attributes:
1832 ids, names, dupnames, source, and classes
1835 bullet is used to record the style of bullet from the input data.
1836 In documents processed from reStructuredText, it contains one of "-",
1837 "+", or "*". It may be ignored in processing.
1839 <!-- == compound_body_subelement -->
1844 name=
"u:outputClass"/>
1848 select=
"../@bullet"/>
1849 &tSP; <!-- space after bullet -->
1850 <xsl:apply-templates/>
1853 <!-- ******************************************************************** -->
1857 enumtype is used to record the intended enumeration sequence, one of
1858 "arabic" (1, 2, 3, ...), "loweralpha" (a, b, c, ..., z), "upperalpha" (A, B,
1859 C, ..., Z), "lowerroman" (i, ii, iii, iv, ..., mmmmcmxcix [4999]), or
1860 "upperroman" (I, II, III, IV, ..., MMMMCMXCIX [4999]).
1861 prefix stores the formatting characters used before the enumerator. In
1862 documents originating from reStructuredText data, it will contain either ""
1863 (empty string) or "(" (left parenthesis). It may or may not affect
1865 suffix stores the formatting characters used after the enumerator. In
1866 documents originating from reStructuredText data, it will contain either "."
1867 (period) or ")" (right parenthesis). Depending on the capabilities of the
1868 output format, this attribute may or may not affect processing.
1869 start contains the ordinal value of the first item in the list, in
1870 decimal. For lists beginning at value 1 ("1", "a", "A", "i", or "I"), this
1871 attribute may be omitted.
1874 <!-- == compound_body_subelement -->
1877 mode=
"enumerated_list">
1879 name=
"u:outputClass"/>
1883 name=
"u:outputEnumerator"/>
1884 <xsl:apply-templates/>
1887 <!-- Outputs a complete enumerator when called in an
1888 enumerated_list/list_item -->
1890 name=
"u:outputEnumerator">
1891 <!-- Use parent's numeration attribute -->
1894 select=
"../@enumtype"/>
1895 <!-- Determine starting point -->
1902 select=
"../@start"/>
1910 <!-- Determine position of this item in its real context -->
1915 select=
"generate-id()"/>
1916 <!-- Generate the right current node list -->
1918 select=
"../list_item">
1920 test=
"generate-id() = $wanted">
1922 select=
"position()"/>
1926 <!-- Determine encoding of the number for the given numeration -->
1930 name=
"u:position2Enumerator">
1933 select=
"$enumType"/>
1936 select=
"$position"/>
1940 </xsl:call-template>
1942 <!-- Determine encoding of the maximum number -->
1946 name=
"u:position2Enumerator">
1949 select=
"$enumType"/>
1952 select=
"count(../list_item)"/>
1956 </xsl:call-template>
1958 <!-- Output complete enumerator -->
1960 select=
"../@prefix"/>
1964 select=
"../@suffix"/>
1965 <!-- Output at least one trailing space -->
1967 <!-- Output more whitespace to align with the maximum enumerator -->
1969 test=
"$enumType != 'lowerroman' and $enumType != 'upperroman'">
1970 <!-- Assumes that the maximum number has maximum string length -->
1972 select=
"str:padding(string-length($max) - string-length($cur))"/>
1976 <!-- Determine the right ordinal enumerator based on the parameters -->
1978 name=
"u:position2Enumerator">
1985 <!-- Determine logical number -->
1988 select=
"$start - 1 + $position"/>
1991 test=
"$enumType = 'arabic'">
1996 test=
"$enumType = 'loweralpha'">
1998 select=
"substring('abcdefghijklmnopqrstzuvwxyz', $ordinal, 1)"/>
2001 test=
"$enumType = 'upperalpha'">
2003 select=
"substring('ABCDEFGHIJKLMNOPQRSTZUVWXYZ', $ordinal, 1)"/>
2005 <!-- TODO Support for counting roman numbers -->
2007 test=
"$enumType = 'lowerroman'">
2008 <xsl:text>i
</xsl:text>
2011 test=
"$enumType = 'upperroman'">
2012 <xsl:text>I
</xsl:text>
2017 <!-- ******************************************************************** -->
2018 <!-- ******************************************************************** -->
2021 Content Model: (title?, tgroup+)
2022 Attributes: The table element contains the common attributes and:
2023 frame, colsep, rowsep, pgwide
2025 <!-- == compound_body_element -->
2029 name=
"u:outputClass"/>
2032 <xsl:apply-templates
2036 <!-- TODO A table title must be rendered by using the `.. table::'
2040 <xsl:apply-templates
2046 <!-- ******************************************************************** -->
2049 Content Model: (colspec*, thead?, tbody)
2050 Attributes: The tgroup element contains the common attributes and:
2051 cols, colsep, rowsep, align
2053 <!-- == compound_body_subelement -->
2056 <xsl:apply-templates/>
2059 <!-- ******************************************************************** -->
2062 Content Model: EMPTY
2063 Attributes: The colspec element contains the common attributes and:
2064 colnum, colname, colwidth, colsep, rowsep, align, char, charoff
2066 The colwidth attribute gives the width of the respective column in characters
2067 including padding whitespace but no separator markup.
2069 <!-- == simple_body_subelement -->
2070 <!-- @colwidth needed by children but element has no own output -->
2074 <!-- ******************************************************************** -->
2077 Content Model: (row+)
2078 Attributes: The thead element contains the common attributes and:
2081 <!-- == compound_body_subelement -->
2084 <xsl:apply-templates/>
2088 Content Model: (row+)
2089 Attributes: The tbody element contains the common attributes and:
2092 <!-- == compound_body_subelement -->
2095 <xsl:apply-templates/>
2098 <!-- ******************************************************************** -->
2101 Content Model: (entry+)
2102 Attributes: The row element contains the common attributes and:
2105 <!-- == compound_body_subelement -->
2108 <!-- Separator line above unless first row of a tbody with no previous
2109 thead (in this case the separator line is output already as the
2110 closing separator line of thead) -->
2112 test=
"position() > 1 or parent::thead or parent::tbody and not(../../thead)">
2114 name=
"u:rowSeparatorLine"/>
2116 <!-- Determine heights in physical lines of all entries -->
2123 <!-- Catch the text of all entries -->
2124 <xsl:apply-templates/>
2126 <!-- Compute height of this entry; leading and trailing EOL must be
2129 select=
"string-length($text) - string-length(translate($text, '
', '')) - 1"/>
2130 &tSP; <!-- A space as a list separator -->
2133 <!-- Determine maximum height so every entry must be this high -->
2136 select=
"math:max(str:tokenize(normalize-space($heights)))"/>
2137 <!-- Output all the physical lines of this row -->
2145 select=
"$maxHeight"/>
2146 </xsl:call-template>
2147 <!-- Output final separator line if this is the last row -->
2149 test=
"position() = last()">
2151 name=
"u:rowSeparatorLine">
2154 <!-- Determine correct character for the separator line -->
2157 test=
"parent::thead">
2167 </xsl:call-template>
2171 <!-- Output physical line $currentLine of a row and continue until
2172 line $maxLine is output -->
2176 name=
"currentLine"/>
2180 test=
"$currentLine <= $maxLine">
2181 <!-- If there are still physical lines to output do it -->
2184 <!-- Leading bar -->
2185 <xsl:text>|
</xsl:text>
2186 <xsl:apply-templates>
2189 select=
"$currentLine"/>
2190 </xsl:apply-templates>
2191 <!-- End of this physical line -->
2193 <!-- Continue with the next physical line -->
2198 select=
"$currentLine + 1"/>
2202 </xsl:call-template>
2206 <!-- Output a separator line with all the right characters -->
2208 name=
"u:rowSeparatorLine">
2214 <xsl:text>+
</xsl:text>
2216 select=
"../../colspec">
2218 select=
"str:padding(@colwidth, $char)"/>
2219 <xsl:text>+
</xsl:text>
2224 <!-- ******************************************************************** -->
2227 Content Model: (%body.elements;)*
2228 Attributes: The entry element contains the common attributes and:
2229 colname, namest, morerows, colsep, rowsep, align, char, charoff, valign and
2232 <!-- == compound_body_subelement -->
2235 <!-- TODO `classes` attribute needs support -->
2236 <!-- This is called in two ways; if $currentLine = 0 all physical lines
2237 of this entry must be output; if $currentLine > 0 the physical line
2238 with exactly this number shall be output -->
2244 select=
"position() + sum(preceding-sibling::entry/@morecols)"/>
2245 <!-- Determine width in characters needed for this entry -->
2249 name=
"u:computeEntryWidth">
2252 select=
"../../../colspec"/>
2258 select=
"@morecols"/>
2259 </xsl:call-template>
2261 <!-- Output the entry completely or a certain physical line -->
2263 name=
"u:outputEntry">
2266 <!-- Capture physical lines of the entry in a variable -->
2267 <xsl:apply-templates/>
2273 name=
"expectedIndent">
2274 <!-- Capture indent for the entry generated by the normal template
2275 rules to remove it later -->
2281 select=
"$currentLine"/>
2282 </xsl:call-template>
2283 <!-- Final bar after the entry -->
2284 <xsl:text>|
</xsl:text>
2287 <!-- Compute width of the entry -->
2289 name=
"u:computeEntryWidth">
2290 <!-- The colspec elements of all columns -->
2293 <!-- Column of this entry -->
2296 <!-- Number of columns this entry spans -->
2306 <!-- If entry spans multiple columns compute their width -->
2308 name=
"u:computeEntryWidth">
2311 select=
"$colspecs"/>
2314 select=
"$column + 1"/>
2317 select=
"$span - 1"/>
2318 <!-- Add the separator character and the following column width -->
2321 select=
"$sum + 1 + $colspecs[$column]/@colwidth"/>
2322 </xsl:call-template>
2325 <!-- Does not span more columns so return sum and width of this
2328 select=
"$sum + $colspecs[$column]/@colwidth"/>
2333 <!-- Outputs one or all lines of a table entry as a string trimmed left and
2336 name=
"u:outputEntry">
2337 <!-- Width of the entry; there is no provision for actual physical lines
2338 longer than this width -->
2341 <!-- The string containing the remaining physical lines; may be an empty
2346 <!-- The indendation which is expected to be prefixed before every
2349 name=
"expectedIndent"
2351 <!-- Is this the first call to this template -->
2355 <!-- Number of physical line to output or 0 to output all lines -->
2359 <!-- Output is wanted if all or the first physical line are to be
2363 select=
"$outputLine = 0 or $outputLine = 1"/>
2365 name=
"stringLFHalfTrimmed">
2368 test=
"$isFirst and substring($string, 1, 1) = '
'">
2369 <!-- Remove leading linefeed if this is the first time -->
2371 select=
"substring($string, 2)"/>
2380 name=
"stringLFTrimmed">
2383 test=
"$isFirst and substring($stringLFHalfTrimmed, string-length($stringLFHalfTrimmed), 1) = '
'">
2384 <!-- Remove trailing linefeed if this is the first time -->
2386 select=
"substring($stringLFHalfTrimmed, 1, string-length($stringLFHalfTrimmed) - 1)"/>
2390 select=
"$stringLFHalfTrimmed"/>
2394 <!-- Determine remaining lines after the first one -->
2396 name=
"remainingLines">
2398 test=
"contains($stringLFTrimmed, '
')">
2400 select=
"substring-after($stringLFTrimmed, '
')"/>
2405 <!-- If this physical line must be output determine the first physical
2411 test=
"string-length($remainingLines)">
2413 select=
"substring-before($stringLFTrimmed, '
')"/>
2417 select=
"$stringLFTrimmed"/>
2421 <!-- Remove the leading indentation from the physical line which is
2422 brought there by the normal templates -->
2426 test=
"string-length($firstLine)">
2427 <!-- Trim only non-empty lines -->
2429 select=
"substring-after($firstLine, $expectedIndent)"/>
2432 <!-- Pad the line with a leading and a trailing space -->
2435 select=
"concat(' ', $trimmed, ' ')"/>
2436 <!-- Output the padded value -->
2439 <!-- Fill up the width of the entry with spaces -->
2441 test=
"$width - string-length($padded) < 0">
2443 <xsl:text>WARNING: Table column too narrow (minimum:
</xsl:text>
2445 select=
"string-length($padded)"/>
2446 <xsl:text>)
</xsl:text>
2451 select=
"str:padding($width - string-length($padded))"/>
2454 test=
"$outputLine > 1 or $outputLine = 0 and string-length($remainingLines)">
2455 <!-- If a following physical line must be output or if all physical
2456 lines shall be output and there are remaining physical lines -->
2458 test=
"$outputLine = 0">
2459 <!-- Output linefeed only if we output all the lines -->
2462 <!-- Output the remaining lines -->
2464 name=
"u:outputEntry">
2470 select=
"$remainingLines"/>
2472 name=
"expectedIndent"
2473 select=
"$expectedIndent"/>
2481 test=
"$outputLine = 0">
2487 select=
"$outputLine - 1"/>
2491 </xsl:call-template>
2495 <!-- ******************************************************************** -->
2496 <!-- ******************************************************************** -->
2498 <!-- == inline_element -->
2500 match=
"citation_reference">
2502 name=
"u:bkslshEscPre"/>
2503 <xsl:text>[
</xsl:text>
2504 <xsl:apply-templates/>
2505 <xsl:text>]_
</xsl:text>
2507 name=
"u:bkslshEscSuf"/>
2510 <!-- ******************************************************************** -->
2512 <!-- == inline_element -->
2516 name=
"u:bkslshEscPre"/>
2517 <xsl:text>*
</xsl:text>
2518 <xsl:apply-templates/>
2519 <xsl:text>*
</xsl:text>
2521 name=
"u:bkslshEscSuf"/>
2524 <!-- ******************************************************************** -->
2526 <!-- user-numbered footnotes lack @auto -->
2527 <!-- == inline_element -->
2529 match=
"footnote_reference[not(@auto)]">
2531 name=
"u:bkslshEscPre"/>
2532 <xsl:text>[
</xsl:text>
2535 <xsl:text>]_
</xsl:text>
2537 name=
"u:bkslshEscSuf"/>
2538 <!-- child paragraph provides blank line -->
2541 <!-- automatically numbered footnotes have @auto -->
2542 <!-- if @names is different from label content, it is a named footnote -->
2543 <!-- == inline_element -->
2545 match=
"footnote_reference[@auto='1']">
2550 test=
"not(starts-with(//footnote[@ids=$ref]/@names, 'TARGET_NOTE:\ '))">
2551 <!-- Not a generated footnote reference for a `.. target-notes::';
2552 such footnote reference and the preceding space should be
2553 embedded in `generated'! -->
2555 name=
"u:bkslshEscPre"/>
2556 <xsl:text>[#
</xsl:text>
2558 test=
"//footnote[@ids=$ref]/@names != //footnote[@ids=$ref]/label">
2560 name=
"u:outputNames">
2563 select=
"//footnote[@ids=$ref]/@names"/>
2564 </xsl:call-template>
2566 <xsl:text>]_
</xsl:text>
2568 name=
"u:bkslshEscSuf"/>
2572 <!-- automatically symboled footnotes have @auto=* -->
2573 <!-- == inline_element -->
2575 match=
"footnote_reference[@auto='*']">
2577 name=
"u:bkslshEscPre"/>
2578 <xsl:text>[*]_
</xsl:text>
2580 name=
"u:bkslshEscSuf"/>
2583 <!-- ******************************************************************** -->
2586 Content Model: %text.model;
2588 <!-- == inline_element -->
2592 name=
"u:bkslshEscPre"/>
2593 <xsl:text>``
</xsl:text>
2594 <xsl:apply-templates/>
2595 <xsl:text>``
</xsl:text>
2597 name=
"u:bkslshEscSuf"/>
2600 <!-- ******************************************************************** -->
2602 <!-- Attribute combinations found in `standard' text and other examples:
2603 @refuri = standalone hyperlink
2604 @ids @refid = TOC, probably all in <generated>
2605 @name @refuri with matching <target> in document = named external hyperlink _
2606 @name @refuri immediately followed by matching <target> = named embedded URI _
2607 @name @refuri with no matching <target> in document = anonymous embedded URI __
2608 @anonymous @name @refuri with no matching <target> in document = anonymous explicit URI __
2609 @name @refid = internal cross-reference _
2610 @anonymous @name @refid = anonymous implicit internal reference __
2611 @name @refid image = clickable image to internal reference _
2612 @refuri image = clickable image to standalone hyperlink
2614 A target matches if target/@names contains the lower cased, whitespace
2615 quoted reference/@name
2618 <!-- Standalone hyperlink -->
2619 <!-- == inline_element -->
2621 match=
"reference[not(@name or @anonymous)]">
2623 name=
"u:bkslshEscPre"/>
2626 test=
"starts-with(., 'PEP ')">
2627 <xsl:text>:PEP:`
</xsl:text>
2629 select=
"substring-after(., 'PEP ')"/>
2630 <xsl:text>`
</xsl:text>
2633 test=
"starts-with(., 'RFC ')">
2634 <xsl:text>:RFC:`
</xsl:text>
2636 select=
"substring-after(., 'RFC ')"/>
2637 <xsl:text>`
</xsl:text>
2640 <xsl:apply-templates/>
2644 name=
"u:bkslshEscSuf"/>
2647 <!-- External references -->
2648 <!-- == inline_element -->
2650 match=
"reference[@name and @refuri]">
2651 <!-- Determine normalized name by downcasing it -->
2654 select=
"translate(normalize-space(@name), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')"/>
2657 select=
"str:replace($normalized, ' ', '\ ')"/>
2660 select=
"//target[contains(@names, $quoted)]"/>
2662 name=
"u:inlineReference">
2665 select=
"not($matching) or @anonymous"/>
2668 select=
"not(@anonymous) and (not($matching) or generate-id(following-sibling::node()[1]) = generate-id($matching))"/>
2669 </xsl:call-template>
2672 <!-- Internal references -->
2673 <!-- == inline_element -->
2675 match=
"reference[@name and @refid]">
2677 name=
"u:inlineReference">
2680 select=
"@anonymous"/>
2681 </xsl:call-template>
2684 <!-- Image references -->
2685 <!-- == inline_element -->
2687 match=
"reference[image]">
2688 <!-- All done by the `image' tag -->
2689 <xsl:apply-templates/>
2692 <!-- ******************************************************************** -->
2695 Content Model: %text.model;
2697 <!-- == inline_element -->
2701 name=
"u:bkslshEscPre"/>
2702 <xsl:text>**
</xsl:text>
2703 <xsl:apply-templates/>
2704 <xsl:text>**
</xsl:text>
2706 name=
"u:bkslshEscSuf"/>
2709 <!-- ******************************************************************** -->
2711 <!-- == inline_element -->
2715 name=
"u:bkslshEscPre"/>
2716 <xsl:text>:sub:`
</xsl:text>
2717 <xsl:apply-templates/>
2718 <xsl:text>`
</xsl:text>
2720 name=
"u:bkslshEscSuf"/>
2723 <!-- ******************************************************************** -->
2725 <!-- == inline_element -->
2727 match=
"superscript">
2729 name=
"u:bkslshEscPre"/>
2730 <xsl:text>:sup:`
</xsl:text>
2731 <xsl:apply-templates/>
2732 <xsl:text>`
</xsl:text>
2734 name=
"u:bkslshEscSuf"/>
2737 <!-- ******************************************************************** -->
2739 <!-- The target element has various roles depending on context; they are
2740 all handled here -->
2741 <!-- == simple_body_element == inline_element == directive -->
2746 test=
"name(preceding-sibling::*[1]) = 'reference'">
2747 <!-- An embedded inline target - handled by the reference itself -->
2750 test=
"contains($inline_containers, concat('*', name(..), '*'))">
2751 <!-- An inline target of some sort -->
2753 name=
"u:inlineReference">
2757 </xsl:call-template>
2761 <!-- An anonymous target directive -->
2763 name=
"u:outputClass"/>
2766 <xsl:text>__
</xsl:text>
2771 name=
"u:outputNamesRefid"/>
2772 <xsl:text>_
</xsl:text>
2783 test=
"@names | @refid">
2784 <!-- A target directive -->
2786 name=
"u:outputClass"/>
2789 <xsl:text>.. _
</xsl:text>
2794 name=
"u:outputNamesRefid"/>
2799 select=
"contains(@names, ':')"/>
2801 test=
"$quoteNeeded">
2802 <xsl:text>`
</xsl:text>
2805 name=
"u:outputNames"/>
2807 test=
"$quoteNeeded">
2808 <xsl:text>`
</xsl:text>
2812 <xsl:text>:
</xsl:text>
2815 <xsl:text> </xsl:text>
2822 <!-- Should not happen -->
2824 name=
"u:notSupported"/>
2829 <!-- ******************************************************************** -->
2832 Content Model: %text.model;
2834 <!-- == inline_element -->
2836 match=
"title_reference">
2838 name=
"u:bkslshEscPre"/>
2839 <xsl:text>`
</xsl:text>
2840 <xsl:apply-templates/>
2841 <xsl:text>`
</xsl:text>
2843 name=
"u:bkslshEscSuf"/>
2846 <!-- ******************************************************************** -->
2849 Content Model: %text.model;
2851 <!-- == inline_element -->
2854 <!-- TODO `role' directives must be generated for plain and derived
2855 user-defined roles. -->
2857 name=
"u:bkslshEscPre"/>
2858 <xsl:text>:
</xsl:text>
2861 <xsl:text>:`
</xsl:text>
2862 <xsl:apply-templates/>
2863 <xsl:text>`
</xsl:text>
2865 name=
"u:bkslshEscSuf"/>
2868 <!-- ******************************************************************** -->
2870 <!-- TODO `meta` directive must be implemented. -->
2872 <!-- ******************************************************************** -->
2875 Docutils wraps generated elements around text that is inserted (generated) by
2876 Docutils; i.e., text that was not in the document, like section numbers
2877 inserted by the "sectnum" directive.
2879 <!-- == inline_element -->
2883 <!-- == inline_element -->
2885 match=
"problematic">
2886 <!-- Simply output the contained text because this is probably the
2892 <!-- == compound_body_element -->
2894 match=
"system_message"/>
2896 <!-- ******************************************************************** -->
2897 <!-- ******************************************************************** -->
2900 When a block of text contains linefeeds, it was indented relative to a marker
2909 <!-- ******************************************************************** -->
2910 <!-- ******************************************************************** -->
2912 <!-- Add a blank line if necessary and indent -->
2921 <!-- ******************************************************************** -->
2923 <!-- Add a blank line in certain contexts -->
2926 <xsl:apply-templates
2927 mode=
"blankSkipInline"
2928 select=
"preceding::*[1]"/>
2931 <!-- Find the preceding element we are really interested in and act
2932 according to this element -->
2934 mode=
"blankSkipInline"
2937 <!-- Skip all inline elements and body subelements and check their
2940 test=
"contains(concat($inline_elements, $simple_body_subelements, $compound_body_subelements), concat('*', name(.), '*'))">
2941 <xsl:apply-templates
2942 mode=
"blankSkipInline"
2946 <!-- Reached the type of element we decide on -->
2948 test=
"contains($blank_after, concat('*', name(.), '*'))">
2955 <!-- ******************************************************************** -->
2958 Indent a block if it's a child of...
2991 <!-- This is only for `bullet_list/list_item';
2992 `enumerated_list/list_item' is handled special -->
2997 name=
"definition_list_item"
3003 name=
"option_list_item"
3005 <!-- This is also the indentation if block_quote comes as one of the
3006 special directives -->
3011 name=
"literal_block"
3021 <!-- Do indent according to ancestor -->
3024 <!-- In some cases the ancestors to indent for need to be determined
3025 by the calling template -->
3028 select=
"ancestor::*"/>
3030 select=
"$ancestors">
3036 test=
"contains($directives, concat('*', $this, '*'))">
3037 <!-- TODO Indentation of lines after some directives must be
3038 indented to align with the directive instead of a
3039 fixed indentation; however, this is rather complicated
3040 since identation for parameters should be fixed -->
3042 select=
"str:padding(3)"/>
3045 test=
"$this = 'list_item' and parent::enumerated_list">
3046 <!-- Enumerated list items base their indentation on the
3051 name=
"u:outputEnumerator"/>
3054 select=
"str:padding(string-length($enumerator))"/>
3058 select=
"str:padding(document('')//data:lookup/node[@name=$this]/@indent)"/>
3064 <!-- ******************************************************************** -->
3066 <!-- Indent a text containing line feeds correctly -->
3072 <!-- A fixed indentation may be given by caller -->
3075 <!-- If not given compute it -->
3081 test=
"contains($string,'
')">
3082 <!-- Output first physical line -->
3084 select=
"substring-before($string, '
')"/>
3086 <!-- Indent before the next line -->
3089 <!-- Output remaining physical lines -->
3094 select=
"substring-after($string, '
')"/>
3098 </xsl:call-template>
3100 <!-- String does not contain newline, so just output it -->
3108 <!-- ******************************************************************** -->
3110 <!-- Do output for those elements which do fold their inline content -->
3112 name=
"u:outputFolding">
3113 <!-- The prefix text to be output before the body -->
3117 <!-- The indentation for this body -->
3124 select=
"ancestor-or-self::*"/>
3125 </xsl:call-template>
3129 <!-- TODO Whitespace count of inline literals must be preserved -->
3130 <xsl:apply-templates/>
3132 <!-- Always output prefix with all trailing and leading spaces -->
3137 test=
"$fold > 0">
3140 select=
"normalize-space($string)"/>
3143 test=
"$string = ''">
3144 <!-- Empty strings need no output -->
3147 test=
"$normalized = ''">
3148 <!-- Only white-space in string; output a single space here -->
3152 <!-- Output leading white-space here -->
3154 test=
"normalize-space(substring($string, 1, 1)) = ''">
3158 name=
"u:indentFold">
3161 select=
"$normalized"/>
3167 select=
"string-length($indent) + string-length($prefix)"/>
3168 </xsl:call-template>
3169 <!-- Output trailing white-space here -->
3171 test=
"normalize-space(substring($string, string-length($string), 1)) = ''">
3185 <!-- ******************************************************************** -->
3187 <!-- Indent a string with folding -->
3189 name=
"u:indentFold">
3190 <!-- Normalized string to output -->
3193 <!-- Indentation to use for a new line -->
3196 <!-- Current output column -->
3197 <!-- TODO This is not a correct assumption for field definitions where
3198 the field name effectively determines the column of the first
3202 select=
"string-length($indent)"/>
3203 <!-- Do we start on a new (indented) line? -->
3210 <!-- TODO Quoted spaces must not end a word -->
3212 test=
"contains($string, ' ')">
3214 select=
"substring-before($string, ' ')"/>
3224 select=
"substring-after($string, ' ')"/>
3227 test=
"$string = ''"/>
3230 <!-- Output at least first word -->
3232 select=
"$firstWord"/>
3234 name=
"u:indentFold">
3243 select=
"$cursorColumn + string-length($firstWord)"/>
3247 </xsl:call-template>
3250 test=
"$cursorColumn + 1 + string-length($firstWord) > $fold">
3251 <!-- Line would get too long; start new line, indent and continue -->
3256 name=
"u:indentFold">
3265 select=
"string-length($indent)"/>
3269 </xsl:call-template>
3272 <!-- In a line and first word fits; separate and add word -->
3275 select=
"$firstWord"/>
3277 name=
"u:indentFold">
3286 select=
"$cursorColumn + 1 + string-length($firstWord)"/>
3290 </xsl:call-template>
3295 <!-- ******************************************************************** -->
3297 <!-- Output attributes of the current element as a field list -->
3303 <!-- Ancestors are needed for determining indentation; caller may give
3307 select=
"ancestor-or-self::*"/>
3310 <!-- Skip URIs based on parent -->
3312 test=
"name() != 'uri' and name() != 'xml:space'">
3317 select=
"$ancestors"/>
3318 </xsl:call-template>
3323 <!-- Output one attribute of the current element as a field list -->
3332 <!-- Ancestors are needed for determining indentation; caller may give
3336 select=
"ancestor::*"/>
3341 select=
"$ancestors"/>
3342 </xsl:call-template>
3343 <xsl:text>:
</xsl:text>
3346 test=
"$name = 'classes'">
3347 <xsl:text>class
</xsl:text>
3354 <xsl:text>:
</xsl:text>
3357 <xsl:text> </xsl:text>
3364 <!-- ******************************************************************** -->
3366 <!-- Output `\' or `\ ' before some inline element if necessary -->
3368 name=
"u:bkslshEscPre">
3369 <!-- Get the sibling node directly before the current element -->
3372 select=
"preceding-sibling::node()[1]"/>
3374 <!-- No sibling before this node -->
3376 test=
"not($before)"/>
3377 <!-- Element directly before this - must be another inline element -->
3379 test=
"name($before)">
3380 <!-- So separate it by a quoted space -->
3381 <xsl:text>\
</xsl:text>
3383 <!-- Node directly before this is text - check it -->
3385 test=
"not(contains(concat($apos, ' 
	
"([{<-/:'), substring($before, string-length($before), 1)))">
3386 <!-- Does not end in one of the allowed characters so separate it -->
3387 <xsl:text>\
</xsl:text>
3392 <!-- Output `\' after some inline element if necessary -->
3394 name=
"u:bkslshEscSuf">
3395 <!-- Get the sibling node directly after the current element -->
3398 select=
"following-sibling::node()[1]"/>
3400 <!-- No sibling after this node -->
3402 test=
"not($after)"/>
3403 <!-- Element directly after this - must be another inline element
3406 test=
"name($after)"/>
3407 <!-- Node directly after this is text - check it -->
3409 test=
"not(contains(concat($apos, ' 
	
")]}>-/:.,;!?\'), substring($after, 1, 1)))">
3410 <!-- Does not start with one of the allowed characters so separate
3412 <xsl:text>\
</xsl:text>
3417 <!-- ******************************************************************** -->
3420 name=
"u:notSupported">
3423 <xsl:text>######## NOT SUPPORTED: `
</xsl:text>
3426 <xsl:text>' ########
</xsl:text>
3430 <!-- ******************************************************************** -->
3434 <!-- Length of the rendered(!) text -->
3437 <!-- Depth 1 and 2 are document title and subtitle while depths
3438 greater than 2 are normal section titles -->
3441 <!-- Test whether a overline is wanted at all -->
3443 test=
"substring($adornment, 2 * ($depth - 1) + 1, 1) = 'o'">
3445 select=
"str:padding($length, substring($adornment, 2 * ($depth - 1) + 2, 1))"/>
3452 <!-- Length of the rendered(!) text -->
3455 <!-- Depth 1 and 2 are document title and subtitle while depths
3456 greater than 2 are normal section titles -->
3460 select=
"str:padding($length, substring($adornment, 2 * ($depth - 1) + 2, 1))"/>
3464 <!-- ******************************************************************** -->
3466 <!-- Output a non-standalone reference or target -->
3468 name=
"u:inlineReference">
3475 <!-- Is this a target instead of a reference? -->
3483 name=
"u:bkslshEscPre"/>
3484 <!-- Delimiter only if link contains other than alphanumerics -->
3488 test=
"* or translate($text, '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', '') or $embedded">
3489 <xsl:text>`
</xsl:text>
3494 <xsl:text>_
</xsl:text>
3497 select=
"$delimiter"/>
3498 <xsl:apply-templates
3502 <xsl:text> <</xsl:text>
3505 <xsl:text>></xsl:text>
3508 select=
"$delimiter"/>
3510 test=
"not($isTarget)">
3511 <xsl:text>_
</xsl:text>
3514 <xsl:text>_
</xsl:text>
3518 name=
"u:bkslshEscSuf"/>
3521 <!-- ******************************************************************** -->
3523 <!-- Output a class directive for the directly following element. -->
3524 <!-- TODO A class directive can also be used as a container putting the
3525 respective attribute to its content; however, this is not
3526 reflected in XML - you'd need to check a sequence of elements
3527 whether they all have the same attribute; furthermore class
3528 settings for block quotes needs to be treated special -->
3530 name=
"u:outputClass">
3531 <!-- Blank line already output? -->
3533 name=
"alreadyBlanked"
3535 <!-- Indentation already output? -->
3537 name=
"alreadyIndented"
3539 <!-- Add a blank line after class directive? -->
3546 test=
"not($alreadyBlanked)">
3551 test=
"not($alreadyIndented)">
3555 <xsl:text>.. class::
</xsl:text>
3566 <!-- ******************************************************************** -->
3568 <!-- Output a names attribute at index considering quoted spaces. -->
3570 name=
"u:outputNames">
3571 <!-- Blank line already output? -->
3579 select=
"str:replace(str:tokenize(normalize-space(str:replace($names, '\ ', '|')))[position() = $index + 1], '|', ' ')"/>
3582 <!-- ******************************************************************** -->
3584 <!-- Output a names attribute for a refid. -->
3586 name=
"u:outputNamesRefid">
3590 <!-- Determine the elements which is referred -->
3593 select=
"//*[@ids and math:max(dyn:map(str:tokenize(normalize-space(@ids)), 'number($refid = .)')) > 0]"/>
3595 name=
"u:outputNames">
3598 select=
"$refElem/@names"/>
3601 select=
"math:max(dyn:map(str:tokenize(normalize-space($refElem/@ids)), 'number($refid = .) * position() - 1'))"/>
3602 </xsl:call-template>
3605 <!-- ******************************************************************** -->
3606 <!-- ******************************************************************** -->
3608 <!-- Report unknown tags -->
3612 <xsl:text>`
</xsl:text>
3615 <xsl:text>' encountered
</xsl:text>
3618 <xsl:text> in `
</xsl:text>
3620 select=
"name(parent::*)"/>
3621 <xsl:text>'
</xsl:text>
3623 <xsl:text>, but no template matches.
</xsl:text>
3629 <!-- ********************************************************************** -->
3630 <!-- ********************************************************************** -->
3631 <!-- ********************************************************************** -->
3632 <!-- POD manual page
3636 xml2rst-nopy.xsl - An XSLT script to convert Docutils XML to reStructuredText
3640 xsltproc docutils.xml xml2rst-nopy.xsl
3644 Today B<xml2rst-nopy.xsl> is not the recommended way to use
3645 B<xml2rst>. The preferred way is to install B<lxml> and use
3646 B<xml2rst.py> instead.
3650 B<xml2rst-nopy.xsl> is an XSLT script to convert Docutils XML to
3651 reStructuredText. You can use your favorite XSLT processor supporting
3652 EXSLT (e.g. xsltproc from the Gnome project) to generate
3653 reStructuredText from the Docutils intermediate XML representation.
3654 Its main use is to generate reStructuredText from some other format
3655 where a converter to Docutils XML already exists.
3659 The following options are supported. They are XSLT parameters for the
3660 whole script and must be given to the XSLT processor by the respective
3661 option (xsltproc: B<- -param> or B<- -stringparam>).
3667 Configures title markup to use so different styles can be requested
3670 The value of the parameter must be a string made up of a sequence of
3671 character pairs. The first character of a pair is C<o> (overline) or
3672 C<u> (underline) and the second character is the character to use for
3675 The first and the second character pair is used for document title and
3676 subtitle, the following pairs are used for section titles where the
3677 third pair is used for the top level section title.
3679 Defaults to C<o=o-u=u-u~u:u.u`>.
3683 Configures whether long text lines in paragraphs should be folded and
3684 to which length. This option is for input not coming from reST which
3685 may have no internal line feeds in plain text strings.
3687 If folding is enabled text strings not in a line feed preserving
3688 context are first white-space normalized and then broken according to
3689 the folding rules. Folding rules put out the first word and continue
3690 to do so with the following words unless the next word would cross
3691 the folding boundary. Words are delimited by white-space.
3693 Defaults to C<0>, i.e. no folding.
3697 =head2 Unsupported features
3699 It is generally not possible to create an exact reproduction of an
3700 original reStructuredText source from an intermediate XML file. The
3701 reason is that Docutils transports pretty much but not all information
3702 of the original source into the XML. Also the sequence is changed
3705 However, the coverage of Docutils features of B<xml2rst-nopy.xsl> is
3706 pretty good. A few minor features are not supported:
3710 =item * Fully minimized style for literal blocks
3712 =item * Substitution references for C<replace::> substitutions
3714 =item * Counting roman numbers in enumerated lists
3716 =item * Special table types like C<list-table::> and C<csv-table::>
3718 =item * Custom role definitions
3724 Installation is not necessary. Just use the file as downloaded with
3725 your favorite XSLT processor supporting EXSLT. For instance you can
3726 use B<xsltproc> from the Gnome project.
3730 Stefan Merten <smerten@oekonux.de> based on works by David Priest.
3734 This program is licensed under the terms of the GPL. See
3736 http://www.gnu.org/licenses/gpl.txt
3742 http://www.merten-home.de/FreeSoftware/xml2rst/