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"/>
1846 test=
"name(*[1]) != 'bullet_list'">
1847 <!-- Start the list item only if the first child is not another list -->
1851 select=
"../@bullet"/>
1852 &tSP; <!-- space after bullet -->
1854 <xsl:apply-templates/>
1857 <!-- ******************************************************************** -->
1861 enumtype is used to record the intended enumeration sequence, one of
1862 "arabic" (1, 2, 3, ...), "loweralpha" (a, b, c, ..., z), "upperalpha" (A, B,
1863 C, ..., Z), "lowerroman" (i, ii, iii, iv, ..., mmmmcmxcix [4999]), or
1864 "upperroman" (I, II, III, IV, ..., MMMMCMXCIX [4999]).
1865 prefix stores the formatting characters used before the enumerator. In
1866 documents originating from reStructuredText data, it will contain either ""
1867 (empty string) or "(" (left parenthesis). It may or may not affect
1869 suffix stores the formatting characters used after the enumerator. In
1870 documents originating from reStructuredText data, it will contain either "."
1871 (period) or ")" (right parenthesis). Depending on the capabilities of the
1872 output format, this attribute may or may not affect processing.
1873 start contains the ordinal value of the first item in the list, in
1874 decimal. For lists beginning at value 1 ("1", "a", "A", "i", or "I"), this
1875 attribute may be omitted.
1878 <!-- == compound_body_subelement -->
1881 mode=
"enumerated_list">
1883 name=
"u:outputClass"/>
1887 name=
"u:outputEnumerator"/>
1888 <xsl:apply-templates/>
1891 <!-- Outputs a complete enumerator when called in an
1892 enumerated_list/list_item -->
1894 name=
"u:outputEnumerator">
1895 <!-- Use parent's numeration attribute -->
1898 select=
"../@enumtype"/>
1899 <!-- Determine starting point -->
1906 select=
"../@start"/>
1914 <!-- Determine position of this item in its real context -->
1919 select=
"generate-id()"/>
1920 <!-- Generate the right current node list -->
1922 select=
"../list_item">
1924 test=
"generate-id() = $wanted">
1926 select=
"position()"/>
1930 <!-- Determine encoding of the number for the given numeration -->
1934 name=
"u:position2Enumerator">
1937 select=
"$enumType"/>
1940 select=
"$position"/>
1944 </xsl:call-template>
1946 <!-- Determine encoding of the maximum number -->
1950 name=
"u:position2Enumerator">
1953 select=
"$enumType"/>
1956 select=
"count(../list_item)"/>
1960 </xsl:call-template>
1962 <!-- Output complete enumerator -->
1964 select=
"../@prefix"/>
1968 select=
"../@suffix"/>
1969 <!-- Output at least one trailing space -->
1971 <!-- Output more whitespace to align with the maximum enumerator -->
1973 test=
"$enumType != 'lowerroman' and $enumType != 'upperroman'">
1974 <!-- Assumes that the maximum number has maximum string length -->
1976 select=
"str:padding(string-length($max) - string-length($cur))"/>
1980 <!-- Determine the right ordinal enumerator based on the parameters -->
1982 name=
"u:position2Enumerator">
1989 <!-- Determine logical number -->
1992 select=
"$start - 1 + $position"/>
1995 test=
"$enumType = 'arabic'">
2000 test=
"$enumType = 'loweralpha'">
2002 select=
"substring('abcdefghijklmnopqrstzuvwxyz', $ordinal, 1)"/>
2005 test=
"$enumType = 'upperalpha'">
2007 select=
"substring('ABCDEFGHIJKLMNOPQRSTZUVWXYZ', $ordinal, 1)"/>
2009 <!-- TODO Support for counting roman numbers -->
2011 test=
"$enumType = 'lowerroman'">
2012 <xsl:text>i
</xsl:text>
2015 test=
"$enumType = 'upperroman'">
2016 <xsl:text>I
</xsl:text>
2021 <!-- ******************************************************************** -->
2022 <!-- ******************************************************************** -->
2025 Content Model: (title?, tgroup+)
2026 Attributes: The table element contains the common attributes and:
2027 frame, colsep, rowsep, pgwide
2029 <!-- == compound_body_element -->
2033 name=
"u:outputClass"/>
2036 <xsl:apply-templates
2040 <!-- TODO A table title must be rendered by using the `.. table::'
2044 <xsl:apply-templates
2050 <!-- ******************************************************************** -->
2053 Content Model: (colspec*, thead?, tbody)
2054 Attributes: The tgroup element contains the common attributes and:
2055 cols, colsep, rowsep, align
2057 <!-- == compound_body_subelement -->
2060 <xsl:apply-templates/>
2063 <!-- ******************************************************************** -->
2066 Content Model: EMPTY
2067 Attributes: The colspec element contains the common attributes and:
2068 colnum, colname, colwidth, colsep, rowsep, align, char, charoff
2070 The colwidth attribute gives the width of the respective column in characters
2071 including padding whitespace but no separator markup.
2073 <!-- == simple_body_subelement -->
2074 <!-- @colwidth needed by children but element has no own output -->
2078 <!-- ******************************************************************** -->
2081 Content Model: (row+)
2082 Attributes: The thead element contains the common attributes and:
2085 <!-- == compound_body_subelement -->
2088 <xsl:apply-templates/>
2092 Content Model: (row+)
2093 Attributes: The tbody element contains the common attributes and:
2096 <!-- == compound_body_subelement -->
2099 <xsl:apply-templates/>
2102 <!-- ******************************************************************** -->
2105 Content Model: (entry+)
2106 Attributes: The row element contains the common attributes and:
2109 <!-- == compound_body_subelement -->
2112 <!-- Separator line above unless first row of a tbody with no previous
2113 thead (in this case the separator line is output already as the
2114 closing separator line of thead) -->
2116 test=
"position() > 1 or parent::thead or parent::tbody and not(../../thead)">
2118 name=
"u:rowSeparatorLine"/>
2120 <!-- Determine heights in physical lines of all entries -->
2127 <!-- Catch the text of all entries -->
2128 <xsl:apply-templates/>
2130 <!-- Compute height of this entry; leading and trailing EOL must be
2133 select=
"string-length($text) - string-length(translate($text, '
', '')) - 1"/>
2134 &tSP; <!-- A space as a list separator -->
2137 <!-- Determine maximum height so every entry must be this high -->
2140 select=
"math:max(str:tokenize(normalize-space($heights)))"/>
2141 <!-- Output all the physical lines of this row -->
2149 select=
"$maxHeight"/>
2150 </xsl:call-template>
2151 <!-- Output final separator line if this is the last row -->
2153 test=
"position() = last()">
2155 name=
"u:rowSeparatorLine">
2158 <!-- Determine correct character for the separator line -->
2161 test=
"parent::thead">
2171 </xsl:call-template>
2175 <!-- Output physical line $currentLine of a row and continue until
2176 line $maxLine is output -->
2180 name=
"currentLine"/>
2184 test=
"$currentLine <= $maxLine">
2185 <!-- If there are still physical lines to output do it -->
2188 <!-- Leading bar -->
2189 <xsl:text>|
</xsl:text>
2190 <xsl:apply-templates>
2193 select=
"$currentLine"/>
2194 </xsl:apply-templates>
2195 <!-- End of this physical line -->
2197 <!-- Continue with the next physical line -->
2202 select=
"$currentLine + 1"/>
2206 </xsl:call-template>
2210 <!-- Output a separator line with all the right characters -->
2212 name=
"u:rowSeparatorLine">
2218 <xsl:text>+
</xsl:text>
2220 select=
"../../colspec">
2222 select=
"str:padding(@colwidth, $char)"/>
2223 <xsl:text>+
</xsl:text>
2228 <!-- ******************************************************************** -->
2231 Content Model: (%body.elements;)*
2232 Attributes: The entry element contains the common attributes and:
2233 colname, namest, morerows, colsep, rowsep, align, char, charoff, valign and
2236 <!-- == compound_body_subelement -->
2239 <!-- TODO `classes` attribute needs support -->
2240 <!-- This is called in two ways; if $currentLine = 0 all physical lines
2241 of this entry must be output; if $currentLine > 0 the physical line
2242 with exactly this number shall be output -->
2248 select=
"position() + sum(preceding-sibling::entry/@morecols)"/>
2249 <!-- Determine width in characters needed for this entry -->
2253 name=
"u:computeEntryWidth">
2256 select=
"../../../colspec"/>
2262 select=
"@morecols"/>
2263 </xsl:call-template>
2265 <!-- Output the entry completely or a certain physical line -->
2267 name=
"u:outputEntry">
2270 <!-- Capture physical lines of the entry in a variable -->
2271 <xsl:apply-templates/>
2277 name=
"expectedIndent">
2278 <!-- Capture indent for the entry generated by the normal template
2279 rules to remove it later -->
2285 select=
"$currentLine"/>
2286 </xsl:call-template>
2287 <!-- Final bar after the entry -->
2288 <xsl:text>|
</xsl:text>
2291 <!-- Compute width of the entry -->
2293 name=
"u:computeEntryWidth">
2294 <!-- The colspec elements of all columns -->
2297 <!-- Column of this entry -->
2300 <!-- Number of columns this entry spans -->
2310 <!-- If entry spans multiple columns compute their width -->
2312 name=
"u:computeEntryWidth">
2315 select=
"$colspecs"/>
2318 select=
"$column + 1"/>
2321 select=
"$span - 1"/>
2322 <!-- Add the separator character and the following column width -->
2325 select=
"$sum + 1 + $colspecs[$column]/@colwidth"/>
2326 </xsl:call-template>
2329 <!-- Does not span more columns so return sum and width of this
2332 select=
"$sum + $colspecs[$column]/@colwidth"/>
2337 <!-- Outputs one or all lines of a table entry as a string trimmed left and
2340 name=
"u:outputEntry">
2341 <!-- Width of the entry; there is no provision for actual physical lines
2342 longer than this width -->
2345 <!-- The string containing the remaining physical lines; may be an empty
2350 <!-- The indendation which is expected to be prefixed before every
2353 name=
"expectedIndent"
2355 <!-- Is this the first call to this template -->
2359 <!-- Number of physical line to output or 0 to output all lines -->
2363 <!-- Output is wanted if all or the first physical line are to be
2367 select=
"$outputLine = 0 or $outputLine = 1"/>
2369 name=
"stringLFHalfTrimmed">
2372 test=
"$isFirst and substring($string, 1, 1) = '
'">
2373 <!-- Remove leading linefeed if this is the first time -->
2375 select=
"substring($string, 2)"/>
2384 name=
"stringLFTrimmed">
2387 test=
"$isFirst and substring($stringLFHalfTrimmed, string-length($stringLFHalfTrimmed), 1) = '
'">
2388 <!-- Remove trailing linefeed if this is the first time -->
2390 select=
"substring($stringLFHalfTrimmed, 1, string-length($stringLFHalfTrimmed) - 1)"/>
2394 select=
"$stringLFHalfTrimmed"/>
2398 <!-- Determine remaining lines after the first one -->
2400 name=
"remainingLines">
2402 test=
"contains($stringLFTrimmed, '
')">
2404 select=
"substring-after($stringLFTrimmed, '
')"/>
2409 <!-- If this physical line must be output determine the first physical
2415 test=
"string-length($remainingLines)">
2417 select=
"substring-before($stringLFTrimmed, '
')"/>
2421 select=
"$stringLFTrimmed"/>
2425 <!-- Remove the leading indentation from the physical line which is
2426 brought there by the normal templates -->
2430 test=
"string-length($firstLine)">
2431 <!-- Trim only non-empty lines -->
2433 select=
"substring-after($firstLine, $expectedIndent)"/>
2436 <!-- Pad the line with a leading and a trailing space -->
2439 select=
"concat(' ', $trimmed, ' ')"/>
2440 <!-- Output the padded value -->
2443 <!-- Fill up the width of the entry with spaces -->
2445 test=
"$width - string-length($padded) < 0">
2447 <xsl:text>WARNING: Table column too narrow (minimum:
</xsl:text>
2449 select=
"string-length($padded)"/>
2450 <xsl:text>)
</xsl:text>
2455 select=
"str:padding($width - string-length($padded))"/>
2458 test=
"$outputLine > 1 or $outputLine = 0 and string-length($remainingLines)">
2459 <!-- If a following physical line must be output or if all physical
2460 lines shall be output and there are remaining physical lines -->
2462 test=
"$outputLine = 0">
2463 <!-- Output linefeed only if we output all the lines -->
2466 <!-- Output the remaining lines -->
2468 name=
"u:outputEntry">
2474 select=
"$remainingLines"/>
2476 name=
"expectedIndent"
2477 select=
"$expectedIndent"/>
2485 test=
"$outputLine = 0">
2491 select=
"$outputLine - 1"/>
2495 </xsl:call-template>
2499 <!-- ******************************************************************** -->
2500 <!-- ******************************************************************** -->
2502 <!-- == inline_element -->
2504 match=
"citation_reference">
2506 name=
"u:bkslshEscPre"/>
2507 <xsl:text>[
</xsl:text>
2508 <xsl:apply-templates/>
2509 <xsl:text>]_
</xsl:text>
2511 name=
"u:bkslshEscSuf"/>
2514 <!-- ******************************************************************** -->
2516 <!-- == inline_element -->
2518 match=
"substitution_reference">
2520 name=
"u:bkslshEscPre"/>
2521 <xsl:text>|
</xsl:text>
2522 <xsl:apply-templates/>
2523 <xsl:text>|
</xsl:text>
2525 name=
"u:bkslshEscSuf"/>
2528 <!-- ******************************************************************** -->
2530 <!-- == inline_element -->
2534 name=
"u:bkslshEscPre"/>
2535 <xsl:text>*
</xsl:text>
2536 <xsl:apply-templates/>
2537 <xsl:text>*
</xsl:text>
2539 name=
"u:bkslshEscSuf"/>
2542 <!-- ******************************************************************** -->
2544 <!-- user-numbered footnotes lack @auto -->
2545 <!-- == inline_element -->
2547 match=
"footnote_reference[not(@auto)]">
2549 name=
"u:bkslshEscPre"/>
2550 <xsl:text>[
</xsl:text>
2553 <xsl:text>]_
</xsl:text>
2555 name=
"u:bkslshEscSuf"/>
2556 <!-- child paragraph provides blank line -->
2559 <!-- automatically numbered footnotes have @auto -->
2560 <!-- if @names is different from label content, it is a named footnote -->
2561 <!-- == inline_element -->
2563 match=
"footnote_reference[@auto='1']">
2568 test=
"not(starts-with(//footnote[@ids=$ref]/@names, 'TARGET_NOTE:\ '))">
2569 <!-- Not a generated footnote reference for a `.. target-notes::';
2570 such footnote reference and the preceding space should be
2571 embedded in `generated'! -->
2573 name=
"u:bkslshEscPre"/>
2574 <xsl:text>[#
</xsl:text>
2576 test=
"//footnote[@ids=$ref]/@names != //footnote[@ids=$ref]/label">
2578 name=
"u:outputNames">
2581 select=
"//footnote[@ids=$ref]/@names"/>
2582 </xsl:call-template>
2584 <xsl:text>]_
</xsl:text>
2586 name=
"u:bkslshEscSuf"/>
2590 <!-- automatically symboled footnotes have @auto=* -->
2591 <!-- == inline_element -->
2593 match=
"footnote_reference[@auto='*']">
2595 name=
"u:bkslshEscPre"/>
2596 <xsl:text>[*]_
</xsl:text>
2598 name=
"u:bkslshEscSuf"/>
2601 <!-- ******************************************************************** -->
2604 Content Model: %text.model;
2606 <!-- == inline_element -->
2610 name=
"u:bkslshEscPre"/>
2611 <xsl:text>``
</xsl:text>
2612 <xsl:apply-templates/>
2613 <xsl:text>``
</xsl:text>
2615 name=
"u:bkslshEscSuf"/>
2618 <!-- ******************************************************************** -->
2620 <!-- Attribute combinations found in `standard' text and other examples:
2621 @refuri = standalone hyperlink
2622 @ids @refid = TOC, probably all in <generated>
2623 @name @refuri with matching <target> in document = named external hyperlink _
2624 @name @refuri immediately followed by matching <target> = named embedded URI _
2625 @name @refuri with no matching <target> in document = anonymous embedded URI __
2626 @anonymous @name @refuri with no matching <target> in document = anonymous explicit URI __
2627 @name @refid = internal cross-reference _
2628 @anonymous @name @refid = anonymous implicit internal reference __
2629 @name @refid image = clickable image to internal reference _
2630 @refuri image = clickable image to standalone hyperlink
2632 A target matches if target/@names contains the lower cased, whitespace
2633 quoted reference/@name
2636 <!-- Standalone hyperlink -->
2637 <!-- == inline_element -->
2639 match=
"reference[not(@name or @anonymous)]">
2641 name=
"u:bkslshEscPre"/>
2644 test=
"starts-with(., 'PEP ')">
2645 <xsl:text>:PEP:`
</xsl:text>
2647 select=
"substring-after(., 'PEP ')"/>
2648 <xsl:text>`
</xsl:text>
2651 test=
"starts-with(., 'RFC ')">
2652 <xsl:text>:RFC:`
</xsl:text>
2654 select=
"substring-after(., 'RFC ')"/>
2655 <xsl:text>`
</xsl:text>
2658 <xsl:apply-templates/>
2662 name=
"u:bkslshEscSuf"/>
2665 <!-- External references -->
2666 <!-- == inline_element -->
2668 match=
"reference[@name and @refuri]">
2669 <!-- Determine normalized name by downcasing it -->
2672 select=
"translate(normalize-space(@name), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')"/>
2675 select=
"str:replace($normalized, ' ', '\ ')"/>
2678 select=
"//target[contains(@names, $quoted)]"/>
2680 name=
"u:inlineReference">
2683 select=
"not($matching) or @anonymous"/>
2686 select=
"not(@anonymous) and (not($matching) or generate-id(following-sibling::node()[1]) = generate-id($matching))"/>
2687 </xsl:call-template>
2690 <!-- Internal references -->
2691 <!-- == inline_element -->
2693 match=
"reference[@name and @refid]">
2695 name=
"u:inlineReference">
2698 select=
"@anonymous"/>
2699 </xsl:call-template>
2702 <!-- Image references -->
2703 <!-- == inline_element -->
2705 match=
"reference[image]">
2706 <!-- All done by the `image' tag -->
2707 <xsl:apply-templates/>
2710 <!-- ******************************************************************** -->
2713 Content Model: %text.model;
2715 <!-- == inline_element -->
2719 name=
"u:bkslshEscPre"/>
2720 <xsl:text>**
</xsl:text>
2721 <xsl:apply-templates/>
2722 <xsl:text>**
</xsl:text>
2724 name=
"u:bkslshEscSuf"/>
2727 <!-- ******************************************************************** -->
2729 <!-- == inline_element -->
2733 name=
"u:bkslshEscPre"/>
2734 <xsl:text>:sub:`
</xsl:text>
2735 <xsl:apply-templates/>
2736 <xsl:text>`
</xsl:text>
2738 name=
"u:bkslshEscSuf"/>
2741 <!-- ******************************************************************** -->
2743 <!-- == inline_element -->
2745 match=
"superscript">
2747 name=
"u:bkslshEscPre"/>
2748 <xsl:text>:sup:`
</xsl:text>
2749 <xsl:apply-templates/>
2750 <xsl:text>`
</xsl:text>
2752 name=
"u:bkslshEscSuf"/>
2755 <!-- ******************************************************************** -->
2757 <!-- The target element has various roles depending on context; they are
2758 all handled here -->
2759 <!-- == simple_body_element == inline_element == directive -->
2764 test=
"name(preceding-sibling::*[1]) = 'reference'">
2765 <!-- An embedded inline target - handled by the reference itself -->
2768 test=
"contains($inline_containers, concat('*', name(..), '*'))">
2769 <!-- An inline target of some sort -->
2771 name=
"u:inlineReference">
2775 </xsl:call-template>
2779 <!-- An anonymous target directive -->
2781 name=
"u:outputClass"/>
2784 <xsl:text>__
</xsl:text>
2789 name=
"u:outputNamesRefid"/>
2790 <xsl:text>_
</xsl:text>
2801 test=
"@names | @refid">
2802 <!-- A target directive -->
2804 name=
"u:outputClass"/>
2807 <xsl:text>.. _
</xsl:text>
2812 name=
"u:outputNamesRefid"/>
2817 select=
"contains(@names, ':')"/>
2819 test=
"$quoteNeeded">
2820 <xsl:text>`
</xsl:text>
2823 name=
"u:outputNames"/>
2825 test=
"$quoteNeeded">
2826 <xsl:text>`
</xsl:text>
2830 <xsl:text>:
</xsl:text>
2833 <xsl:text> </xsl:text>
2840 <!-- Should not happen -->
2842 name=
"u:notSupported"/>
2847 <!-- ******************************************************************** -->
2850 Content Model: %text.model;
2852 <!-- == inline_element -->
2854 match=
"title_reference">
2856 name=
"u:bkslshEscPre"/>
2857 <xsl:text>`
</xsl:text>
2858 <xsl:apply-templates/>
2859 <xsl:text>`
</xsl:text>
2861 name=
"u:bkslshEscSuf"/>
2864 <!-- ******************************************************************** -->
2867 Content Model: %text.model;
2869 <!-- == inline_element -->
2872 <!-- TODO `role' directives must be generated for plain and derived
2873 user-defined roles. -->
2875 name=
"u:bkslshEscPre"/>
2876 <xsl:text>:
</xsl:text>
2879 <xsl:text>:`
</xsl:text>
2880 <xsl:apply-templates/>
2881 <xsl:text>`
</xsl:text>
2883 name=
"u:bkslshEscSuf"/>
2886 <!-- ******************************************************************** -->
2888 <!-- TODO `meta` directive must be implemented. -->
2890 <!-- ******************************************************************** -->
2893 Docutils wraps generated elements around text that is inserted (generated) by
2894 Docutils; i.e., text that was not in the document, like section numbers
2895 inserted by the "sectnum" directive.
2897 <!-- == inline_element -->
2901 <!-- == inline_element -->
2903 match=
"problematic">
2904 <!-- Simply output the contained text because this is probably the
2910 <!-- == compound_body_element -->
2912 match=
"system_message"/>
2914 <!-- ******************************************************************** -->
2915 <!-- ******************************************************************** -->
2918 When a block of text contains linefeeds, it was indented relative to a marker
2927 <!-- ******************************************************************** -->
2928 <!-- ******************************************************************** -->
2930 <!-- Add a blank line if necessary and indent -->
2939 <!-- ******************************************************************** -->
2941 <!-- Add a blank line in certain contexts -->
2944 <xsl:apply-templates
2945 mode=
"blankSkipInline"
2946 select=
"preceding::*[1]"/>
2949 <!-- Find the preceding element we are really interested in and act
2950 according to this element -->
2952 mode=
"blankSkipInline"
2955 <!-- Skip all inline elements and body subelements and check their
2958 test=
"contains(concat($inline_elements, $simple_body_subelements, $compound_body_subelements), concat('*', name(.), '*'))">
2959 <xsl:apply-templates
2960 mode=
"blankSkipInline"
2964 <!-- Reached the type of element we decide on -->
2966 test=
"contains($blank_after, concat('*', name(.), '*'))">
2973 <!-- ******************************************************************** -->
2976 Indent a block if it's a child of...
3009 <!-- This is only for `bullet_list/list_item';
3010 `enumerated_list/list_item' is handled special -->
3015 name=
"definition_list_item"
3021 name=
"option_list_item"
3023 <!-- This is also the indentation if block_quote comes as one of the
3024 special directives -->
3029 name=
"literal_block"
3039 <!-- Do indent according to ancestor -->
3042 <!-- In some cases the ancestors to indent for need to be determined
3043 by the calling template -->
3046 select=
"ancestor::*"/>
3048 select=
"$ancestors">
3054 test=
"contains($directives, concat('*', $this, '*'))">
3055 <!-- TODO Indentation of lines after some directives must be
3056 indented to align with the directive instead of a
3057 fixed indentation; however, this is rather complicated
3058 since identation for parameters should be fixed -->
3060 select=
"str:padding(3)"/>
3063 test=
"$this = 'list_item' and parent::enumerated_list">
3064 <!-- Enumerated list items base their indentation on the
3069 name=
"u:outputEnumerator"/>
3072 select=
"str:padding(string-length($enumerator))"/>
3076 select=
"str:padding(document('')//data:lookup/node[@name=$this]/@indent)"/>
3082 <!-- ******************************************************************** -->
3084 <!-- Indent a text containing line feeds correctly -->
3090 <!-- A fixed indentation may be given by caller -->
3093 <!-- If not given compute it -->
3099 test=
"contains($string,'
')">
3100 <!-- Output first physical line -->
3102 select=
"substring-before($string, '
')"/>
3104 <!-- Indent before the next line -->
3107 <!-- Output remaining physical lines -->
3112 select=
"substring-after($string, '
')"/>
3116 </xsl:call-template>
3118 <!-- String does not contain newline, so just output it -->
3126 <!-- ******************************************************************** -->
3128 <!-- Do output for those elements which do fold their inline content -->
3130 name=
"u:outputFolding">
3131 <!-- The prefix text to be output before the body -->
3135 <!-- The indentation for this body -->
3142 select=
"ancestor-or-self::*"/>
3143 </xsl:call-template>
3147 <!-- TODO Whitespace count of inline literals must be preserved -->
3148 <xsl:apply-templates/>
3150 <!-- Always output prefix with all trailing and leading spaces -->
3155 test=
"$fold > 0">
3158 select=
"normalize-space($string)"/>
3161 test=
"$string = ''">
3162 <!-- Empty strings need no output -->
3165 test=
"$normalized = ''">
3166 <!-- Only white-space in string; output a single space here -->
3170 <!-- Output leading white-space here -->
3172 test=
"normalize-space(substring($string, 1, 1)) = ''">
3176 name=
"u:indentFold">
3179 select=
"$normalized"/>
3185 select=
"string-length($indent) + string-length($prefix)"/>
3186 </xsl:call-template>
3187 <!-- Output trailing white-space here -->
3189 test=
"normalize-space(substring($string, string-length($string), 1)) = ''">
3203 <!-- ******************************************************************** -->
3205 <!-- Indent a string with folding -->
3207 name=
"u:indentFold">
3208 <!-- Normalized string to output -->
3211 <!-- Indentation to use for a new line -->
3214 <!-- Current output column -->
3215 <!-- TODO This is not a correct assumption for field definitions where
3216 the field name effectively determines the column of the first
3220 select=
"string-length($indent)"/>
3221 <!-- Do we start on a new (indented) line? -->
3228 <!-- TODO Quoted spaces must not end a word -->
3230 test=
"contains($string, ' ')">
3232 select=
"substring-before($string, ' ')"/>
3242 select=
"substring-after($string, ' ')"/>
3245 test=
"$string = ''"/>
3248 <!-- Output at least first word -->
3250 select=
"$firstWord"/>
3252 name=
"u:indentFold">
3261 select=
"$cursorColumn + string-length($firstWord)"/>
3265 </xsl:call-template>
3268 test=
"$cursorColumn + 1 + string-length($firstWord) > $fold">
3269 <!-- Line would get too long; start new line, indent and continue -->
3274 name=
"u:indentFold">
3283 select=
"string-length($indent)"/>
3287 </xsl:call-template>
3290 <!-- In a line and first word fits; separate and add word -->
3293 select=
"$firstWord"/>
3295 name=
"u:indentFold">
3304 select=
"$cursorColumn + 1 + string-length($firstWord)"/>
3308 </xsl:call-template>
3313 <!-- ******************************************************************** -->
3315 <!-- Output attributes of the current element as a field list -->
3321 <!-- Ancestors are needed for determining indentation; caller may give
3325 select=
"ancestor-or-self::*"/>
3328 <!-- Skip URIs based on parent -->
3330 test=
"name() != 'uri' and name() != 'xml:space'">
3335 select=
"$ancestors"/>
3336 </xsl:call-template>
3341 <!-- Output one attribute of the current element as a field list -->
3350 <!-- Ancestors are needed for determining indentation; caller may give
3354 select=
"ancestor::*"/>
3359 select=
"$ancestors"/>
3360 </xsl:call-template>
3361 <xsl:text>:
</xsl:text>
3364 test=
"$name = 'classes'">
3365 <xsl:text>class
</xsl:text>
3372 <xsl:text>:
</xsl:text>
3375 <xsl:text> </xsl:text>
3382 <!-- ******************************************************************** -->
3384 <!-- Output `\' or `\ ' before some inline element if necessary -->
3386 name=
"u:bkslshEscPre">
3387 <!-- Get the sibling node directly before the current element -->
3390 select=
"preceding-sibling::node()[1]"/>
3392 <!-- No sibling before this node -->
3394 test=
"not($before)"/>
3395 <!-- Element directly before this - must be another inline element -->
3397 test=
"name($before)">
3398 <!-- So separate it by a quoted space -->
3399 <xsl:text>\
</xsl:text>
3401 <!-- Node directly before this is text - check it -->
3403 test=
"not(contains(concat($apos, ' 
	
"([{<-/:'), substring($before, string-length($before), 1)))">
3404 <!-- Does not end in one of the allowed characters so separate it -->
3405 <xsl:text>\
</xsl:text>
3410 <!-- Output `\' after some inline element if necessary -->
3412 name=
"u:bkslshEscSuf">
3413 <!-- Get the sibling node directly after the current element -->
3416 select=
"following-sibling::node()[1]"/>
3418 <!-- No sibling after this node -->
3420 test=
"not($after)"/>
3421 <!-- Element directly after this - must be another inline element
3424 test=
"name($after)"/>
3425 <!-- Node directly after this is text - check it -->
3427 test=
"not(contains(concat($apos, ' 
	
")]}>-/:.,;!?\'), substring($after, 1, 1)))">
3428 <!-- Does not start with one of the allowed characters so separate
3430 <xsl:text>\
</xsl:text>
3435 <!-- ******************************************************************** -->
3438 name=
"u:notSupported">
3441 <xsl:text>######## NOT SUPPORTED: `
</xsl:text>
3444 <xsl:text>' ########
</xsl:text>
3448 <!-- ******************************************************************** -->
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 -->
3459 <!-- Test whether a overline is wanted at all -->
3461 test=
"substring($adornment, 2 * ($depth - 1) + 1, 1) = 'o'">
3463 select=
"str:padding($length, substring($adornment, 2 * ($depth - 1) + 2, 1))"/>
3470 <!-- Length of the rendered(!) text -->
3473 <!-- Depth 1 and 2 are document title and subtitle while depths
3474 greater than 2 are normal section titles -->
3478 select=
"str:padding($length, substring($adornment, 2 * ($depth - 1) + 2, 1))"/>
3482 <!-- ******************************************************************** -->
3484 <!-- Output a non-standalone reference or target -->
3486 name=
"u:inlineReference">
3493 <!-- Is this a target instead of a reference? -->
3501 name=
"u:bkslshEscPre"/>
3502 <!-- Delimiter only if link contains other than alphanumerics -->
3506 test=
"* or translate($text, '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', '') or $embedded">
3507 <xsl:text>`
</xsl:text>
3512 <xsl:text>_
</xsl:text>
3515 select=
"$delimiter"/>
3516 <xsl:apply-templates
3520 <xsl:text> <</xsl:text>
3523 <xsl:text>></xsl:text>
3526 select=
"$delimiter"/>
3528 test=
"not($isTarget)">
3529 <xsl:text>_
</xsl:text>
3532 <xsl:text>_
</xsl:text>
3536 name=
"u:bkslshEscSuf"/>
3539 <!-- ******************************************************************** -->
3541 <!-- Output a class directive for the directly following element. -->
3542 <!-- TODO A class directive can also be used as a container putting the
3543 respective attribute to its content; however, this is not
3544 reflected in XML - you'd need to check a sequence of elements
3545 whether they all have the same attribute; furthermore class
3546 settings for block quotes needs to be treated special -->
3548 name=
"u:outputClass">
3549 <!-- Blank line already output? -->
3551 name=
"alreadyBlanked"
3553 <!-- Indentation already output? -->
3555 name=
"alreadyIndented"
3557 <!-- Add a blank line after class directive? -->
3564 test=
"not($alreadyBlanked)">
3569 test=
"not($alreadyIndented)">
3573 <xsl:text>.. class::
</xsl:text>
3584 <!-- ******************************************************************** -->
3586 <!-- Output a names attribute at index considering quoted spaces. -->
3588 name=
"u:outputNames">
3589 <!-- Blank line already output? -->
3597 select=
"str:replace(str:tokenize(normalize-space(str:replace($names, '\ ', '|')))[position() = $index + 1], '|', ' ')"/>
3600 <!-- ******************************************************************** -->
3602 <!-- Output a names attribute for a refid. -->
3604 name=
"u:outputNamesRefid">
3608 <!-- Determine the elements which is referred -->
3611 select=
"//*[@ids and math:max(dyn:map(str:tokenize(normalize-space(@ids)), 'number($refid = .)')) > 0]"/>
3613 name=
"u:outputNames">
3616 select=
"$refElem/@names"/>
3619 select=
"math:max(dyn:map(str:tokenize(normalize-space($refElem/@ids)), 'number($refid = .) * position() - 1'))"/>
3620 </xsl:call-template>
3623 <!-- ******************************************************************** -->
3624 <!-- ******************************************************************** -->
3626 <!-- Report unknown tags -->
3630 <xsl:text>`
</xsl:text>
3633 <xsl:text>' encountered
</xsl:text>
3636 <xsl:text> in `
</xsl:text>
3638 select=
"name(parent::*)"/>
3639 <xsl:text>'
</xsl:text>
3641 <xsl:text>, but no template matches.
</xsl:text>
3647 <!-- ********************************************************************** -->
3648 <!-- ********************************************************************** -->
3649 <!-- ********************************************************************** -->
3650 <!-- POD manual page
3654 xml2rst-nopy.xsl - An XSLT script to convert Docutils XML to reStructuredText
3658 xsltproc docutils.xml xml2rst-nopy.xsl
3662 Today B<xml2rst-nopy.xsl> is not the recommended way to use
3663 B<xml2rst>. The preferred way is to install B<lxml> and use
3664 B<xml2rst.py> instead.
3668 B<xml2rst-nopy.xsl> is an XSLT script to convert Docutils XML to
3669 reStructuredText. You can use your favorite XSLT processor supporting
3670 EXSLT (e.g. xsltproc from the Gnome project) to generate
3671 reStructuredText from the Docutils intermediate XML representation.
3672 Its main use is to generate reStructuredText from some other format
3673 where a converter to Docutils XML already exists.
3677 The following options are supported. They are XSLT parameters for the
3678 whole script and must be given to the XSLT processor by the respective
3679 option (xsltproc: B<- -param> or B<- -stringparam>).
3685 Configures title markup to use so different styles can be requested
3688 The value of the parameter must be a string made up of a sequence of
3689 character pairs. The first character of a pair is C<o> (overline) or
3690 C<u> (underline) and the second character is the character to use for
3693 The first and the second character pair is used for document title and
3694 subtitle, the following pairs are used for section titles where the
3695 third pair is used for the top level section title.
3697 Defaults to C<o=o-u=u-u~u:u.u`>.
3701 Configures whether long text lines in paragraphs should be folded and
3702 to which length. This option is for input not coming from reST which
3703 may have no internal line feeds in plain text strings.
3705 If folding is enabled text strings not in a line feed preserving
3706 context are first white-space normalized and then broken according to
3707 the folding rules. Folding rules put out the first word and continue
3708 to do so with the following words unless the next word would cross
3709 the folding boundary. Words are delimited by white-space.
3711 Defaults to C<0>, i.e. no folding.
3715 =head2 Unsupported features
3717 It is generally not possible to create an exact reproduction of an
3718 original reStructuredText source from an intermediate XML file. The
3719 reason is that Docutils transports pretty much but not all information
3720 of the original source into the XML. Also the sequence is changed
3723 However, the coverage of Docutils features of B<xml2rst-nopy.xsl> is
3724 pretty good. A few minor features are not supported:
3728 =item * Fully minimized style for literal blocks
3730 =item * Substitution references for C<replace::> substitutions
3732 =item * Counting roman numbers in enumerated lists
3734 =item * Special table types like C<list-table::> and C<csv-table::>
3736 =item * Custom role definitions
3742 Installation is not necessary. Just use the file as downloaded with
3743 your favorite XSLT processor supporting EXSLT. For instance you can
3744 use B<xsltproc> from the Gnome project.
3748 Stefan Merten <smerten@oekonux.de> based on works by David Priest.
3752 This program is licensed under the terms of the GPL. See
3754 http://www.gnu.org/licenses/gpl.txt
3760 http://www.merten-home.de/FreeSoftware/xml2rst/