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 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/>
473 <!-- ******************************************************************** -->
476 Content Model: ((author, organization?, address?, contact?)+)
477 Attributes: The authors element contains only the common attributes: ids,
478 names, dupnames, source, and classes.
480 In reStructuredText, multiple author's names are separated with semicolons
481 (";") or commas (","); semicolons take precedence. There is currently no way
482 to represent the author's organization, address, or contact in a
483 reStructuredText "Authors" field.
485 <!-- == bibliographic_element == folding_element -->
487 match=
"docinfo/authors">
489 name=
"u:outputFolding">
492 <xsl:text>:
</xsl:text>
495 <xsl:text>:
</xsl:text>
501 Content Model: %text.model;
502 Attributes: All docinfo elements contains the common attributes (ids,
503 names, dupnames, source, and classes)
504 Some docinfo elements also have xml:space.
507 match=
"docinfo/authors/*">
508 <xsl:apply-templates/>
509 <!-- no semicolon after final author -->
511 test=
"generate-id(current()) != generate-id(../*[last()])">
512 <xsl:text>;
</xsl:text>
517 Content Model: (field_name, field_body)
518 Attributes: The field element contains only the common attributes: ids,
519 names, dupnames, source, and classes.
521 <!-- == bibliographic_element -->
523 match=
"docinfo/field">
524 <!-- contents handled by ordinary field lists -->
525 <xsl:apply-templates/>
526 <!-- Supply an EOL because following elements do not recognize this -->
531 Content Model: %text.model;
532 Attributes: All docinfo elements contains the common attributes (ids,
533 names, dupnames, source, and classes)
534 Some docinfo elements also have xml:space.
536 <!-- == bibliographic_element == folding_element -->
538 match=
"docinfo/*[name()!='authors' and name()!='field']">
540 name=
"u:outputFolding">
543 <xsl:text>:
</xsl:text>
546 <xsl:text>:
</xsl:text>
551 <!-- ******************************************************************** -->
555 Attributes: The transition element contains only the common attributes:
556 ids, names, dupnames, source, and classes.
558 <!-- == structural_subelement -->
562 name=
"u:outputClass"/>
563 &tCR; <!-- req: blank line before -->
564 <xsl:text>-----
</xsl:text>
566 <!-- Add a required blank line after unless class follows immediately -->
568 test=
"not(following-sibling::*[1]/@classes)">
573 <!-- ******************************************************************** -->
574 <!-- ******************************************************************** -->
577 IFF there is a /document/title element, it is the publication's title. All
578 other titles will appear within sections.
580 Content Model: %text.model;
581 Attributes: The title element contains the common attributes (ids, names,
582 dupnames, source, and classes), plus refid and auto.
583 refid is used as a backlink to a table of contents entry.
584 auto is used to indicate (with value "1") that the title has been
585 numbered automatically.
587 <!-- == structural_subelement -->
589 match=
"//document/title">
591 name=
"u:outputClass"/>
594 <!-- Catch the title text as it is rendered so its length can be
596 <xsl:apply-templates/>
600 select=
"normalize-space($textWS)"/>
603 select=
"string-length($text)"/>
627 <!-- ******************************************************************** -->
630 Title Underlines are defined by their position within the tree.
632 Content Model: %text.model;
633 Attributes: The title element contains the common attributes (ids, names,
634 dupnames, source, and classes), plus refid and auto.
635 refid is used as a backlink to a table of contents entry.
636 auto is used to indicate (with value "1") that the title has been
637 numbered automatically.
639 <!-- == structural_subelement -->
641 match=
"section/title">
643 name=
"u:outputClass"/>
646 <!-- catch the title text as it is rendered -->
647 <xsl:apply-templates/>
651 select=
"normalize-space($textWS)"/>
654 select=
"string-length($text)"/>
657 select=
"count(ancestor::section)"/>
665 select=
"$depth + 2"/>
677 select=
"$depth + 2"/>
679 <!-- Add a blank line after unless structure follows immediately -->
681 test=
"not(contains(concat($structural_elements, $compound_body_elements), concat('*', name(following-sibling::*[1]), '*')) or following-sibling::*[1]/@classes)">
686 <!-- ******************************************************************** -->
689 Content Model: %text.model;
690 Attributes: The title element contains the common attributes (ids, names,
691 dupnames, source, and classes), plus refid and auto.
692 refid is used as a backlink to a table of contents entry.
693 auto is used to indicate (with value "1") that the title has been
694 numbered automatically.
696 <!-- == structural_subelement -->
700 name=
"u:outputClass">
702 name=
"alreadyBlanked"
705 <!-- blank line provided by parent -->
706 <xsl:apply-templates/>
707 <!-- no EOL: provided by parent -->
710 <!-- ******************************************************************** -->
713 IFF there is a /document/title element, it is the publication's title. All
714 other titles will appear within sections.
716 Content Model: %text.model;
717 Attributes: The subtitle element contains only the common attributes:
718 ids, names, dupnames, source, and classes.
720 <!-- == structural_subelement -->
722 match=
"//document/subtitle">
724 name=
"u:outputClass"/>
727 <!-- Catch the title text as it is rendered -->
728 <xsl:apply-templates/>
732 select=
"normalize-space($textWS)"/>
735 select=
"string-length($text)"/>
737 <!-- always a blank line above -->
762 <!-- ******************************************************************** -->
765 Content Model: %text.model;
766 Attributes: The subtitle element contains only the common attributes: ids,
767 names, dupnames, source, and classes.
769 <!-- == structural_subelement -->
771 match=
"sidebar/subtitle">
773 name=
"u:outputClass"/>
776 <xsl:apply-templates/>
781 <!-- ******************************************************************** -->
782 <!-- ******************************************************************** -->
785 Content Model: %text.model;
786 Attributes: The comment element contains only the common attributes: ids,
787 names, dupnames, source, and classes.
789 <!-- == simple_body_element == folding_element == directive -->
795 name=
"u:outputFolding">
798 <xsl:text>..
</xsl:text>
803 <!-- ******************************************************************** -->
806 Content Model: %text.model;
807 Attributes: The doctest_block element contains the common attributes (ids,
808 names, dupnames, source, and classes), plus xml:space.
810 <!-- == simple_body_element -->
812 match=
"doctest_block">
814 name=
"u:outputClass"/>
817 <xsl:apply-templates/>
821 <!-- ******************************************************************** -->
823 <!-- An image element can have various roles; they are all covered here -->
824 <!-- == simple_body_element == inline_element == directive -->
829 test=
"contains($inline_containers, concat('*', name(..), '*')) and @alt">
830 <!-- An inline image with an `@alt' - must be a substitution
832 <xsl:text>|
</xsl:text>
833 <!-- Original text is lost - use what we have -->
836 <xsl:text>|
</xsl:text>
841 test=
"not(parent::figure)">
843 test=
"not(parent::substitution_definition)">
846 <xsl:text>..
</xsl:text>
848 <xsl:text>image::
</xsl:text>
855 test=
"parent::figure">
856 <!-- `@classes' is special because it is in the parent -->
863 select=
"'figclass'"/>
866 select=
"../@classes"/>
869 select=
"ancestor::*"/>
872 <!-- `@align' is special because it is in the parent -->
885 select=
"ancestor::*"/>
890 <!-- `figure' would add one level of indentation -->
893 select=
"ancestor::*"/>
897 test=
"parent::substitution_definition">
900 <!-- `@alt' only for the real images -->
903 select=
"@*[name() != 'alt']"/>
911 select=
"@*[name() != 'ids' and name() != 'names']"/>
916 test=
"parent::reference">
917 <!-- A clickable image -->
928 <!-- An internal link -->
930 name=
"u:inlineReference">
937 <!-- An external link -->
939 select=
"../@refuri"/>
945 select=
"ancestor-or-self::*"/>
948 <!-- Always blank line after parameter block -->
954 <!-- ******************************************************************** -->
957 Content Model: (line_block | line)+
958 Attributes: The line_block element contains the common attributes (ids,
959 names, dupnames, source, and classes), plus xml:space.
961 <!-- == compound_body_element -->
965 name=
"u:outputClass"/>
968 select=
"name(..) = 'line_block'"/>
970 test=
"not($isEmbedded)">
974 <xsl:apply-templates/>
977 <!-- ******************************************************************** -->
980 Content Model: %text.model;
981 Attributes: The line element contains the common attributes (ids,
982 names, dupnames, source, and classes).
984 <!-- == simple_body_subelement == folding_element -->
988 name=
"u:outputClass"/>
999 <!-- Only for non-empty lines -->
1001 name=
"lineBlockIndent">
1002 <!-- Very special indendation for nested `line_block's -->
1004 select=
"ancestor::line_block[position() > 1]">
1006 select=
"str:padding(4)"/>
1010 name=
"u:outputFolding">
1013 <xsl:text>|
</xsl:text>
1015 select=
"$lineBlockIndent"/>
1019 select=
"concat($indent, ' ', $lineBlockIndent)"/>
1020 </xsl:call-template>
1023 <xsl:text>|
</xsl:text>
1029 <!-- ******************************************************************** -->
1032 Content Model: %text.model;
1033 Attributes: The literal_block element contains the common attributes (ids,
1034 names, dupnames, source, and classes), plus xml:space.
1036 <!-- == simple_body_element == directive -->
1038 match=
"literal_block">
1041 test=
".//*[contains($inline_elements, concat('*', name(), '*'))]">
1042 <!-- If it contains inline elements this is a parsed-literal -->
1045 <xsl:text>.. parsed-literal::
</xsl:text>
1053 name=
"u:outputClass"/>
1054 <!-- TODO Support for the (fully) minimized style would be nice but
1055 is difficult to accomplish because there is a linefeed
1056 already when we arrive here :-( -->
1059 <xsl:text>::
</xsl:text>
1065 name=
"isQuotedLiteral">
1067 name=
"u:isQuotedLiteral"/>
1069 <!-- Indent correctly depending on quoted literal or not -->
1072 test=
"string-length($isQuotedLiteral)">
1077 select=
"ancestor::*"/>
1078 </xsl:call-template>
1079 <xsl:apply-templates
1080 mode=
"quotedLiteral"/>
1087 select=
"ancestor-or-self::*"/>
1088 </xsl:call-template>
1089 <xsl:apply-templates/>
1095 <!-- Indent a text of a quoted literal containing line feeds correctly -->
1098 mode=
"quotedLiteral">
1107 select=
"ancestor::*[position() > 1]"/>
1108 </xsl:call-template>
1110 </xsl:call-template>
1113 <!-- Determine whether `$text' is a quoted literal and return the quote
1116 name=
"u:isQuotedLiteral">
1122 select=
"substring($text, 1, 1)"/>
1124 test=
"contains($adornment_characters, $quote) and substring($text, 1, 1) = $quote">
1125 <!-- Given quote is an adornment character and first character is this
1129 test=
"contains($text, '
')">
1130 <!-- Test the remaining lines -->
1132 name=
"u:isQuotedLiteral">
1135 select=
"substring-after($text, '
')"/>
1139 </xsl:call-template>
1142 <!-- No more lines to test so this is a quoted literal -->
1150 <!-- ******************************************************************** -->
1153 Content Model: %text.model;
1154 Attributes: The paragraph element contains only the common attributes:
1155 ids, names, dupnames, source, and classes.
1157 <!-- == simple_body_element == folding_element -->
1162 select=
"preceding-sibling::*[1]"/>
1163 <!-- Do indent except first element in some compound elements -->
1166 select=
"($previous or not(parent::list_item or parent::field_body or contains($admonitions, concat('*', name(..), '*')))) and name($previous) != 'label'"/>
1167 <!-- Blank line in front if following a body element, except first
1168 elements in some compound elements -->
1171 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')"/>
1177 test=
"$needsIndent">
1183 <!-- This paragraph has a classes attribute - always needs newline and
1186 name=
"u:outputClass">
1188 name=
"alreadyBlanked"
1189 select=
"$needsBlank"/>
1191 name=
"alreadyIndented"
1192 select=
"$needsIndent"/>
1193 </xsl:call-template>
1198 name=
"u:outputFolding"/>
1201 <!-- ******************************************************************** -->
1203 <!-- == simple_body_element -->
1207 name=
"u:notSupported"/>
1210 <!-- ******************************************************************** -->
1212 <!-- == simple_body_element == inline_element == directive -->
1217 test=
"contains($inline_containers, concat('*', name(..), '*'))">
1218 <!-- Used as a custom role -->
1219 <!-- TODO `role' directives must be generated for user-defined raw
1221 <!-- The name of the custom role is not contained in the input -->
1222 <xsl:text>:RAW-ROLE:`
</xsl:text>
1223 <xsl:apply-templates/>
1224 <xsl:text>`
</xsl:text>
1227 <!-- A directive -->
1229 name=
"u:outputClass"/>
1232 <xsl:text>.. raw::
</xsl:text>
1240 select=
"@*[name() != 'format' and name() != 'classes']"/>
1241 </xsl:call-template>
1247 select=
"ancestor-or-self::*"/>
1248 </xsl:call-template>
1249 <xsl:apply-templates/>
1255 <!-- ******************************************************************** -->
1257 <!-- == simple_body_element == folding_element == directive -->
1263 name=
"u:outputFolding">
1266 <xsl:text>.. rubric::
</xsl:text>
1268 </xsl:call-template>
1273 <!-- ******************************************************************** -->
1275 <!-- == compound_body_element == directive -->
1280 <xsl:text>.. compound::
</xsl:text>
1284 <xsl:apply-templates/>
1287 <!-- ******************************************************************** -->
1289 <!-- == compound_body_element == directive -->
1294 <xsl:text>.. container::
</xsl:text>
1302 <xsl:apply-templates/>
1305 <!-- ******************************************************************** -->
1307 <!-- == simple_body_element == directive -->
1309 match=
"substitution_definition">
1310 <!-- More than one child or not a directive is a replacement text -->
1313 select=
"not(* and count(node()) = 1 and contains($directives, concat('*', name(*[1]), '*')))"/>
1318 <xsl:text>.. |
</xsl:text>
1320 name=
"u:outputNames"/>
1321 <xsl:text>|
</xsl:text>
1326 <!-- TODO Substitution references for replace can not be found because
1327 they are not marked as such; embedding them in `generated'
1330 name=
"u:outputFolding">
1335 <xsl:text>replace::
</xsl:text>
1337 </xsl:call-template>
1342 <xsl:apply-templates/>
1347 <!-- ******************************************************************** -->
1350 Content Model: ((%body.elements;)+, attribution?)
1351 Attributes: The block_quote element contains only the common attributes:
1352 ids, names, dupnames, source, and classes.
1354 <!-- == compound_body_element -->
1356 match=
"block_quote">
1358 test=
"@classes = 'epigraph' or @classes = 'highlights' or @classes = 'pull-quote'">
1361 <xsl:text>..
</xsl:text>
1364 <xsl:text>::
</xsl:text>
1369 <xsl:apply-templates/>
1372 <!-- ******************************************************************** -->
1374 <!-- == simple_body_subelement == folding_element -->
1376 match=
"attribution">
1378 name=
"u:outputClass"/>
1379 <!-- blank line between quote and attribution -->
1384 name=
"u:outputFolding">
1387 <xsl:text>--
</xsl:text>
1389 </xsl:call-template>
1392 <!-- ******************************************************************** -->
1394 <!-- == compound_body_element == directive -->
1398 name=
"u:outputClass"/>
1401 <xsl:text>.. [
</xsl:text>
1404 <xsl:text>]
</xsl:text>
1405 <xsl:apply-templates
1406 select=
"*[not(self::label)]"/>
1409 <!-- == simple_body_subelement -->
1411 match=
"citation/label">
1412 <xsl:apply-templates/>
1415 <!-- ******************************************************************** -->
1417 <!-- == compound_body_element == directive -->
1422 <xsl:text>.. figure::
</xsl:text>
1423 <xsl:apply-templates/>
1426 <!-- ******************************************************************** -->
1428 <!-- == simple_body_subelement == folding_element -->
1434 name=
"u:outputFolding"/>
1437 <!-- ******************************************************************** -->
1439 <!-- == compound_body_subelement -->
1442 <xsl:apply-templates/>
1445 <!-- ******************************************************************** -->
1447 <!-- TODO Footnotes should continue on line of definition -->
1449 <!-- user-numbered footnotes lack @auto -->
1450 <!-- == compound_body_element == directive -->
1452 match=
"footnote[not(@auto)]">
1454 name=
"u:outputClass"/>
1457 <xsl:text>.. [
</xsl:text>
1458 <xsl:apply-templates
1460 <xsl:text>]
</xsl:text>
1461 <xsl:apply-templates
1462 select=
"*[not(self::label)]"/>
1465 <!-- autonumbered footnotes have @auto -->
1466 <!-- if the target footnote_reference@names matches its label, it was not a
1467 numbered-name footnote -->
1468 <!-- == compound_body_element == directive -->
1470 match=
"footnote[@auto='1']">
1472 name=
"u:outputClass"/>
1475 <xsl:text>.. [#
</xsl:text>
1477 test=
"@names = @ids">
1479 name=
"u:outputNames"/>
1481 <xsl:text>]
</xsl:text>
1482 <xsl:apply-templates
1483 select=
"*[not(self::label)]"/>
1486 <!-- autosymboled footnotes have @auto -->
1487 <!-- == compound_body_element == directive -->
1489 match=
"footnote[@auto='*']">
1491 name=
"u:outputClass"/>
1494 <xsl:text>.. [*]
</xsl:text>
1495 <xsl:apply-templates
1496 select=
"*[not(self::label)]"/>
1499 <!-- == compound_body_element == directive -->
1501 match=
"footnote[starts-with(@names, 'TARGET_NOTE:\ ')]">
1502 <!-- This is not a footnote but a hint for a directive -->
1504 test=
"generate-id(//footnote[starts-with(@names, 'TARGET_NOTE:\ ')][1]) = generate-id(.)">
1505 <!-- Only for the first one -->
1508 <!-- TODO May have a `classes` attribute -->
1509 <xsl:text>.. target-notes::
</xsl:text>
1514 <!-- == simple_body_subelement -->
1516 match=
"footnote/label">
1517 <xsl:apply-templates/>
1520 <!-- ******************************************************************** -->
1523 Content Model: (list_item +)
1524 Attributes: The bullet_list element contains the common attributes (ids,
1525 names, dupnames, source, and classes), plus bullet.
1526 bullet is used to record the style of bullet from the input data.
1527 In documents processed from reStructuredText, it contains one of "-",
1528 "+", or "*". It may be ignored in processing.
1530 <!-- == compound_body_element -->
1532 match=
"bullet_list">
1534 name=
"u:outputClass"/>
1535 <xsl:apply-templates
1536 mode=
"bullet_list"/>
1539 <!-- ******************************************************************** -->
1542 Content Model: (definition_list_item +)
1543 Attributes: The definition_list element contains only the common
1544 attributes: ids, names, dupnames, source, and classes.
1546 <!-- == compound_body_element -->
1548 match=
"definition_list">
1550 name=
"u:outputClass"/>
1551 <xsl:apply-templates/>
1554 <!-- ******************************************************************** -->
1557 Content Model: (term, classifier?, definition)
1558 Attributes: The definition_list_item element contains only the common
1559 attributes: ids, names, dupnames, source, and classes.
1561 <!-- == compound_body_subelement -->
1563 match=
"definition_list_item">
1565 name=
"u:outputClass"/>
1568 <xsl:apply-templates/>
1571 <!-- ******************************************************************** -->
1574 Content Model: %text.model;
1575 Attributes: The term element contains only the common attributes: ids,
1576 names, dupnames, source, and classes.
1578 <!-- == simple_body_subelement -->
1581 <xsl:apply-templates/>
1584 <!-- ******************************************************************** -->
1587 Content Model: %text.model;
1588 Attributes: The classifier element contains only the common attributes:
1589 ids, names, dupnames, source, and classes.
1591 <!-- == simple_body_subelement -->
1594 <xsl:text> :
</xsl:text>
1595 <xsl:apply-templates/>
1598 <!-- ******************************************************************** -->
1601 Content Model: (%body.elements;)+
1602 Attributes: The definition element contains only the common attributes:
1603 ids, names, dupnames, source, and classes.
1605 <!-- == compound_body_subelement -->
1609 name=
"u:outputClass"/>
1610 <xsl:apply-templates/>
1613 <!-- ******************************************************************** -->
1616 Content Model: (list_item +)
1617 Attributes: The enumerated_list element contains the common attributes
1618 (ids, names, dupnames, source, and classes), plus enumtype, prefix, suffix, and
1620 enumtype is used to record the intended enumeration sequence, one
1621 of "arabic" (1, 2, 3, ...), "loweralpha" (a, b, c, ..., z), "upperalpha" (A,
1622 B, C, ..., Z), "lowerroman" (i, ii, iii, iv, ..., mmmmcmxcix [4999]), or
1623 "upperroman" (I, II, III, IV, ..., MMMMCMXCIX [4999]).
1624 prefix stores the formatting characters used before the enumerator. In
1625 documents originating from reStructuredText data, it will contain either ""
1626 (empty string) or "(" (left parenthesis). It may or may not affect
1628 suffix stores the formatting characters used after the enumerator. In
1629 documents originating from reStructuredText data, it will contain either "."
1630 (period) or ")" (right parenthesis). Depending on the capabilities of the
1631 output format, this attribute may or may not affect processing.
1632 start contains the ordinal value of the first item in the list, in
1633 decimal. For lists beginning at value 1 ("1", "a", "A", "i", or "I"), this
1634 attribute may be omitted.
1636 <!-- == compound_body_element -->
1638 match=
"enumerated_list">
1640 name=
"u:outputClass"/>
1641 <xsl:apply-templates
1642 mode=
"enumerated_list"/>
1645 <!-- ******************************************************************** -->
1648 Content Model: (field +)
1649 Attributes: The field_list element contains only the common attributes:
1650 ids, names, dupnames, source, and classes.
1652 <!-- == compound_body_element -->
1656 name=
"u:outputClass"/>
1657 <xsl:apply-templates/>
1660 <!-- ******************************************************************** -->
1663 Content Model: (field_name, field_body)
1664 Attributes: The field element contains only the common attributes: ids,
1665 names, dupnames, source, and classes.
1667 <!-- == compound_body_subelement -->
1671 name=
"u:outputClass"/>
1674 <xsl:apply-templates/>
1677 <!-- ********************************************************************** -->
1680 Content Model: %text.model;
1681 Attributes: The field_name element contains only the common attributes:
1682 ids, names, dupnames, source, and classes.
1684 <!-- == simple_body_subelement -->
1687 <xsl:text>:
</xsl:text>
1688 <xsl:apply-templates/>
1689 <xsl:text>:
</xsl:text>
1690 <!-- no EOL: field_body starts on same line -->
1693 <!-- ******************************************************************** -->
1696 Content Model: (%body.elements;)*
1697 Attributes: The field_body element contains only the common attributes:
1698 ids, names, dupnames, source, and classes.
1700 <!-- == compound_body_subelement -->
1704 name=
"u:outputClass"/>
1705 <xsl:apply-templates/>
1708 <!-- ******************************************************************** -->
1711 Content Model: (option_list_item +)
1712 Attributes: The option_list element contains only the common attributes:
1713 ids, names, dupnames, source, and classes.
1715 <!-- == compound_body_element -->
1717 match=
"option_list">
1719 name=
"u:outputClass"/>
1722 <xsl:apply-templates/>
1725 <!-- ******************************************************************** -->
1728 Content Model: (option_group, description)
1729 Attributes: The option_list_item element contains only the common
1730 attributes: ids, names, dupnames, source, and classes.
1732 <!-- == compound_body_subelement -->
1734 match=
"option_list_item">
1736 name=
"u:outputClass"/>
1739 <xsl:apply-templates/>
1742 <!-- ******************************************************************** -->
1745 Content Model: (option_group, description)
1746 Attributes: The option_group element contains only the common attributes:
1747 ids, names, dupnames, source, and classes.
1749 <!-- == compound_body_subelement -->
1751 match=
"option_group">
1752 <xsl:apply-templates/>
1756 <!-- ******************************************************************** -->
1759 Content Model: (option_string, option_argument *)
1760 Attributes: The option element contains only the common attributes: ids,
1761 names, dupnames, source, and classes.
1763 <!-- == compound_body_subelement -->
1767 name=
"u:outputClass"/>
1768 <xsl:apply-templates/>
1770 test=
"generate-id(current()) != generate-id(../*[last()])">
1771 <!-- No comma after final option -->
1772 <xsl:text>,
</xsl:text>
1774 <!-- no EOL: description on same line -->
1777 <!-- ******************************************************************** -->
1780 Content Model: (#PCDATA)
1781 Attributes: The option_string element contains only the common attributes:
1782 ids, names, dupnames, source, and classes.
1784 <!-- == simple_body_subelement -->
1786 match=
"option_string">
1787 <xsl:apply-templates/>
1790 <!-- ******************************************************************** -->
1793 Content Model: (#PCDATA)
1794 Attributes: The option_argument element contains the common attributes
1795 (ids, names, dupnames, source, and classes), plus delimiter.
1796 delimiter contains the text preceding the option_argument:
1797 either the text separating it from the option_string (typically
1799 or the text between option arguments (typically either "," or " ").
1801 <!-- == simple_body_subelement -->
1803 match=
"option_argument">
1805 select=
"@delimiter"/>
1806 <xsl:apply-templates/>
1809 <!-- ******************************************************************** -->
1812 Content Model: (%body.elements;)+
1813 Attributes: The description element contains only the common attributes:
1814 ids, names, dupnames, source, and classes.
1816 <!-- == compound_body_subelement -->
1818 match=
"description">
1820 name=
"u:outputClass"/>
1821 <xsl:apply-templates/>
1825 <!-- ******************************************************************** -->
1828 Content Model: (%body.elements;)+
1829 Attributes: The list_item element contains only the common attributes:
1830 ids, names, dupnames, source, and classes
1833 bullet is used to record the style of bullet from the input data.
1834 In documents processed from reStructuredText, it contains one of "-",
1835 "+", or "*". It may be ignored in processing.
1837 <!-- == compound_body_subelement -->
1842 name=
"u:outputClass"/>
1846 select=
"../@bullet"/>
1847 &tSP; <!-- space after bullet -->
1848 <xsl:apply-templates/>
1851 <!-- ******************************************************************** -->
1855 enumtype is used to record the intended enumeration sequence, one of
1856 "arabic" (1, 2, 3, ...), "loweralpha" (a, b, c, ..., z), "upperalpha" (A, B,
1857 C, ..., Z), "lowerroman" (i, ii, iii, iv, ..., mmmmcmxcix [4999]), or
1858 "upperroman" (I, II, III, IV, ..., MMMMCMXCIX [4999]).
1859 prefix stores the formatting characters used before the enumerator. In
1860 documents originating from reStructuredText data, it will contain either ""
1861 (empty string) or "(" (left parenthesis). It may or may not affect
1863 suffix stores the formatting characters used after the enumerator. In
1864 documents originating from reStructuredText data, it will contain either "."
1865 (period) or ")" (right parenthesis). Depending on the capabilities of the
1866 output format, this attribute may or may not affect processing.
1867 start contains the ordinal value of the first item in the list, in
1868 decimal. For lists beginning at value 1 ("1", "a", "A", "i", or "I"), this
1869 attribute may be omitted.
1872 <!-- == compound_body_subelement -->
1875 mode=
"enumerated_list">
1877 name=
"u:outputClass"/>
1881 name=
"u:outputEnumerator"/>
1882 <xsl:apply-templates/>
1885 <!-- Outputs a complete enumerator when called in an
1886 enumerated_list/list_item -->
1888 name=
"u:outputEnumerator">
1889 <!-- Use parent's numeration attribute -->
1892 select=
"../@enumtype"/>
1893 <!-- Determine starting point -->
1900 select=
"../@start"/>
1908 <!-- Determine position of this item in its real context -->
1913 select=
"generate-id()"/>
1914 <!-- Generate the right current node list -->
1916 select=
"../list_item">
1918 test=
"generate-id() = $wanted">
1920 select=
"position()"/>
1924 <!-- Determine encoding of the number for the given numeration -->
1928 name=
"u:position2Enumerator">
1931 select=
"$enumType"/>
1934 select=
"$position"/>
1938 </xsl:call-template>
1940 <!-- Determine encoding of the maximum number -->
1944 name=
"u:position2Enumerator">
1947 select=
"$enumType"/>
1950 select=
"count(../list_item)"/>
1954 </xsl:call-template>
1956 <!-- Output complete enumerator -->
1958 select=
"../@prefix"/>
1962 select=
"../@suffix"/>
1963 <!-- Output at least one trailing space -->
1965 <!-- Output more whitespace to align with the maximum enumerator -->
1967 test=
"$enumType != 'lowerroman' and $enumType != 'upperroman'">
1968 <!-- Assumes that the maximum number has maximum string length -->
1970 select=
"str:padding(string-length($max) - string-length($cur))"/>
1974 <!-- Determine the right ordinal enumerator based on the parameters -->
1976 name=
"u:position2Enumerator">
1983 <!-- Determine logical number -->
1986 select=
"$start - 1 + $position"/>
1989 test=
"$enumType = 'arabic'">
1994 test=
"$enumType = 'loweralpha'">
1996 select=
"substring('abcdefghijklmnopqrstzuvwxyz', $ordinal, 1)"/>
1999 test=
"$enumType = 'upperalpha'">
2001 select=
"substring('ABCDEFGHIJKLMNOPQRSTZUVWXYZ', $ordinal, 1)"/>
2003 <!-- TODO Support for counting roman numbers -->
2005 test=
"$enumType = 'lowerroman'">
2006 <xsl:text>i
</xsl:text>
2009 test=
"$enumType = 'upperroman'">
2010 <xsl:text>I
</xsl:text>
2015 <!-- ******************************************************************** -->
2016 <!-- ******************************************************************** -->
2019 Content Model: (title?, tgroup+)
2020 Attributes: The table element contains the common attributes and:
2021 frame, colsep, rowsep, pgwide
2023 <!-- == compound_body_element -->
2027 name=
"u:outputClass"/>
2030 <xsl:apply-templates
2034 <!-- TODO A table title must be rendered by using the `.. table::'
2038 <xsl:apply-templates
2044 <!-- ******************************************************************** -->
2047 Content Model: (colspec*, thead?, tbody)
2048 Attributes: The tgroup element contains the common attributes and:
2049 cols, colsep, rowsep, align
2051 <!-- == compound_body_subelement -->
2054 <xsl:apply-templates/>
2057 <!-- ******************************************************************** -->
2060 Content Model: EMPTY
2061 Attributes: The colspec element contains the common attributes and:
2062 colnum, colname, colwidth, colsep, rowsep, align, char, charoff
2064 The colwidth attribute gives the width of the respective column in characters
2065 including padding whitespace but no separator markup.
2067 <!-- == simple_body_subelement -->
2068 <!-- @colwidth needed by children but element has no own output -->
2072 <!-- ******************************************************************** -->
2075 Content Model: (row+)
2076 Attributes: The thead element contains the common attributes and:
2079 <!-- == compound_body_subelement -->
2082 <xsl:apply-templates/>
2086 Content Model: (row+)
2087 Attributes: The tbody element contains the common attributes and:
2090 <!-- == compound_body_subelement -->
2093 <xsl:apply-templates/>
2096 <!-- ******************************************************************** -->
2099 Content Model: (entry+)
2100 Attributes: The row element contains the common attributes and:
2103 <!-- == compound_body_subelement -->
2106 <!-- Separator line above unless first row of a tbody with no previous
2107 thead (in this case the separator line is output already as the
2108 closing separator line of thead) -->
2110 test=
"position() > 1 or parent::thead or parent::tbody and not(../../thead)">
2112 name=
"u:rowSeparatorLine"/>
2114 <!-- Determine heights in physical lines of all entries -->
2121 <!-- Catch the text of all entries -->
2122 <xsl:apply-templates/>
2124 <!-- Compute height of this entry; leading and trailing EOL must be
2127 select=
"string-length($text) - string-length(translate($text, '
', '')) - 1"/>
2128 &tSP; <!-- A space as a list separator -->
2131 <!-- Determine maximum height so every entry must be this high -->
2134 select=
"math:max(str:tokenize(normalize-space($heights)))"/>
2135 <!-- Output all the physical lines of this row -->
2143 select=
"$maxHeight"/>
2144 </xsl:call-template>
2145 <!-- Output final separator line if this is the last row -->
2147 test=
"position() = last()">
2149 name=
"u:rowSeparatorLine">
2152 <!-- Determine correct character for the separator line -->
2155 test=
"parent::thead">
2165 </xsl:call-template>
2169 <!-- Output physical line $currentLine of a row and continue until
2170 line $maxLine is output -->
2174 name=
"currentLine"/>
2178 test=
"$currentLine <= $maxLine">
2179 <!-- If there are still physical lines to output do it -->
2182 <!-- Leading bar -->
2183 <xsl:text>|
</xsl:text>
2184 <xsl:apply-templates>
2187 select=
"$currentLine"/>
2188 </xsl:apply-templates>
2189 <!-- End of this physical line -->
2191 <!-- Continue with the next physical line -->
2196 select=
"$currentLine + 1"/>
2200 </xsl:call-template>
2204 <!-- Output a separator line with all the right characters -->
2206 name=
"u:rowSeparatorLine">
2212 <xsl:text>+
</xsl:text>
2214 select=
"../../colspec">
2216 select=
"str:padding(@colwidth, $char)"/>
2217 <xsl:text>+
</xsl:text>
2222 <!-- ******************************************************************** -->
2225 Content Model: (%body.elements;)*
2226 Attributes: The entry element contains the common attributes and:
2227 colname, namest, morerows, colsep, rowsep, align, char, charoff, valign and
2230 <!-- == compound_body_subelement -->
2233 <!-- TODO `classes` attribute needs support -->
2234 <!-- This is called in two ways; if $currentLine = 0 all physical lines
2235 of this entry must be output; if $currentLine > 0 the physical line
2236 with exactly this number shall be output -->
2242 select=
"position() + sum(preceding-sibling::entry/@morecols)"/>
2243 <!-- Determine width in characters needed for this entry -->
2247 name=
"u:computeEntryWidth">
2250 select=
"../../../colspec"/>
2256 select=
"@morecols"/>
2257 </xsl:call-template>
2259 <!-- Output the entry completely or a certain physical line -->
2261 name=
"u:outputEntry">
2264 <!-- Capture physical lines of the entry in a variable -->
2265 <xsl:apply-templates/>
2271 name=
"expectedIndent">
2272 <!-- Capture indent for the entry generated by the normal template
2273 rules to remove it later -->
2279 select=
"$currentLine"/>
2280 </xsl:call-template>
2281 <!-- Final bar after the entry -->
2282 <xsl:text>|
</xsl:text>
2285 <!-- Compute width of the entry -->
2287 name=
"u:computeEntryWidth">
2288 <!-- The colspec elements of all columns -->
2291 <!-- Column of this entry -->
2294 <!-- Number of columns this entry spans -->
2304 <!-- If entry spans multiple columns compute their width -->
2306 name=
"u:computeEntryWidth">
2309 select=
"$colspecs"/>
2312 select=
"$column + 1"/>
2315 select=
"$span - 1"/>
2316 <!-- Add the separator character and the following column width -->
2319 select=
"$sum + 1 + $colspecs[$column]/@colwidth"/>
2320 </xsl:call-template>
2323 <!-- Does not span more columns so return sum and width of this
2326 select=
"$sum + $colspecs[$column]/@colwidth"/>
2331 <!-- Outputs one or all lines of a table entry as a string trimmed left and
2334 name=
"u:outputEntry">
2335 <!-- Width of the entry; there is no provision for actual physical lines
2336 longer than this width -->
2339 <!-- The string containing the remaining physical lines; may be an empty
2344 <!-- The indendation which is expected to be prefixed before every
2347 name=
"expectedIndent"
2349 <!-- Is this the first call to this template -->
2353 <!-- Number of physical line to output or 0 to output all lines -->
2357 <!-- Output is wanted if all or the first physical line are to be
2361 select=
"$outputLine = 0 or $outputLine = 1"/>
2363 name=
"stringLFHalfTrimmed">
2366 test=
"$isFirst and substring($string, 1, 1) = '
'">
2367 <!-- Remove leading linefeed if this is the first time -->
2369 select=
"substring($string, 2)"/>
2378 name=
"stringLFTrimmed">
2381 test=
"$isFirst and substring($stringLFHalfTrimmed, string-length($stringLFHalfTrimmed), 1) = '
'">
2382 <!-- Remove trailing linefeed if this is the first time -->
2384 select=
"substring($stringLFHalfTrimmed, 1, string-length($stringLFHalfTrimmed) - 1)"/>
2388 select=
"$stringLFHalfTrimmed"/>
2392 <!-- Determine remaining lines after the first one -->
2394 name=
"remainingLines">
2396 test=
"contains($stringLFTrimmed, '
')">
2398 select=
"substring-after($stringLFTrimmed, '
')"/>
2403 <!-- If this physical line must be output determine the first physical
2409 test=
"string-length($remainingLines)">
2411 select=
"substring-before($stringLFTrimmed, '
')"/>
2415 select=
"$stringLFTrimmed"/>
2419 <!-- Remove the leading indentation from the physical line which is
2420 brought there by the normal templates -->
2424 test=
"string-length($firstLine)">
2425 <!-- Trim only non-empty lines -->
2427 select=
"substring-after($firstLine, $expectedIndent)"/>
2430 <!-- Pad the line with a leading and a trailing space -->
2433 select=
"concat(' ', $trimmed, ' ')"/>
2434 <!-- Output the padded value -->
2437 <!-- Fill up the width of the entry with spaces -->
2439 test=
"$width - string-length($padded) < 0">
2441 <xsl:text>WARNING: Table column too narrow (minimum:
</xsl:text>
2443 select=
"string-length($padded)"/>
2444 <xsl:text>)
</xsl:text>
2449 select=
"str:padding($width - string-length($padded))"/>
2452 test=
"$outputLine > 1 or $outputLine = 0 and string-length($remainingLines)">
2453 <!-- If a following physical line must be output or if all physical
2454 lines shall be output and there are remaining physical lines -->
2456 test=
"$outputLine = 0">
2457 <!-- Output linefeed only if we output all the lines -->
2460 <!-- Output the remaining lines -->
2462 name=
"u:outputEntry">
2468 select=
"$remainingLines"/>
2470 name=
"expectedIndent"
2471 select=
"$expectedIndent"/>
2479 test=
"$outputLine = 0">
2485 select=
"$outputLine - 1"/>
2489 </xsl:call-template>
2493 <!-- ******************************************************************** -->
2494 <!-- ******************************************************************** -->
2496 <!-- == inline_element -->
2498 match=
"citation_reference">
2500 name=
"u:bkslshEscPre"/>
2501 <xsl:text>[
</xsl:text>
2502 <xsl:apply-templates/>
2503 <xsl:text>]_
</xsl:text>
2505 name=
"u:bkslshEscSuf"/>
2508 <!-- ******************************************************************** -->
2510 <!-- == inline_element -->
2514 name=
"u:bkslshEscPre"/>
2515 <xsl:text>*
</xsl:text>
2516 <xsl:apply-templates/>
2517 <xsl:text>*
</xsl:text>
2519 name=
"u:bkslshEscSuf"/>
2522 <!-- ******************************************************************** -->
2524 <!-- user-numbered footnotes lack @auto -->
2525 <!-- == inline_element -->
2527 match=
"footnote_reference[not(@auto)]">
2529 name=
"u:bkslshEscPre"/>
2530 <xsl:text>[
</xsl:text>
2533 <xsl:text>]_
</xsl:text>
2535 name=
"u:bkslshEscSuf"/>
2536 <!-- child paragraph provides blank line -->
2539 <!-- automatically numbered footnotes have @auto -->
2540 <!-- if @names is different from label content, it is a named footnote -->
2541 <!-- == inline_element -->
2543 match=
"footnote_reference[@auto='1']">
2548 test=
"not(starts-with(//footnote[@ids=$ref]/@names, 'TARGET_NOTE:\ '))">
2549 <!-- Not a generated footnote reference for a `.. target-notes::';
2550 such footnote reference and the preceding space should be
2551 embedded in `generated'! -->
2553 name=
"u:bkslshEscPre"/>
2554 <xsl:text>[#
</xsl:text>
2556 test=
"//footnote[@ids=$ref]/@names != //footnote[@ids=$ref]/label">
2558 name=
"u:outputNames">
2561 select=
"//footnote[@ids=$ref]/@names"/>
2562 </xsl:call-template>
2564 <xsl:text>]_
</xsl:text>
2566 name=
"u:bkslshEscSuf"/>
2570 <!-- automatically symboled footnotes have @auto=* -->
2571 <!-- == inline_element -->
2573 match=
"footnote_reference[@auto='*']">
2575 name=
"u:bkslshEscPre"/>
2576 <xsl:text>[*]_
</xsl:text>
2578 name=
"u:bkslshEscSuf"/>
2581 <!-- ******************************************************************** -->
2584 Content Model: %text.model;
2586 <!-- == inline_element -->
2590 name=
"u:bkslshEscPre"/>
2591 <xsl:text>``
</xsl:text>
2592 <xsl:apply-templates/>
2593 <xsl:text>``
</xsl:text>
2595 name=
"u:bkslshEscSuf"/>
2598 <!-- ******************************************************************** -->
2600 <!-- Attribute combinations found in `standard' text and other examples:
2601 @refuri = standalone hyperlink
2602 @ids @refid = TOC, probably all in <generated>
2603 @name @refuri with matching <target> in document = named external hyperlink _
2604 @name @refuri immediately followed by matching <target> = named embedded URI _
2605 @name @refuri with no matching <target> in document = anonymous embedded URI __
2606 @anonymous @name @refuri with no matching <target> in document = anonymous explicit URI __
2607 @name @refid = internal cross-reference _
2608 @anonymous @name @refid = anonymous implicit internal reference __
2609 @name @refid image = clickable image to internal reference _
2610 @refuri image = clickable image to standalone hyperlink
2612 A target matches if target/@names contains the lower cased, whitespace
2613 quoted reference/@name
2616 <!-- Standalone hyperlink -->
2617 <!-- == inline_element -->
2619 match=
"reference[not(@name or @anonymous)]">
2621 name=
"u:bkslshEscPre"/>
2624 test=
"starts-with(., 'PEP ')">
2625 <xsl:text>:PEP:`
</xsl:text>
2627 select=
"substring-after(., 'PEP ')"/>
2628 <xsl:text>`
</xsl:text>
2631 test=
"starts-with(., 'RFC ')">
2632 <xsl:text>:RFC:`
</xsl:text>
2634 select=
"substring-after(., 'RFC ')"/>
2635 <xsl:text>`
</xsl:text>
2638 <xsl:apply-templates/>
2642 name=
"u:bkslshEscSuf"/>
2645 <!-- External references -->
2646 <!-- == inline_element -->
2648 match=
"reference[@name and @refuri]">
2649 <!-- Determine normalized name by downcasing it -->
2652 select=
"translate(normalize-space(@name), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')"/>
2655 select=
"str:replace($normalized, ' ', '\ ')"/>
2658 select=
"//target[contains(@names, $quoted)]"/>
2660 name=
"u:inlineReference">
2663 select=
"not($matching) or @anonymous"/>
2666 select=
"not(@anonymous) and (not($matching) or generate-id(following-sibling::node()[1]) = generate-id($matching))"/>
2667 </xsl:call-template>
2670 <!-- Internal references -->
2671 <!-- == inline_element -->
2673 match=
"reference[@name and @refid]">
2675 name=
"u:inlineReference">
2678 select=
"@anonymous"/>
2679 </xsl:call-template>
2682 <!-- Image references -->
2683 <!-- == inline_element -->
2685 match=
"reference[image]">
2686 <!-- All done by the `image' tag -->
2687 <xsl:apply-templates/>
2690 <!-- ******************************************************************** -->
2693 Content Model: %text.model;
2695 <!-- == inline_element -->
2699 name=
"u:bkslshEscPre"/>
2700 <xsl:text>**
</xsl:text>
2701 <xsl:apply-templates/>
2702 <xsl:text>**
</xsl:text>
2704 name=
"u:bkslshEscSuf"/>
2707 <!-- ******************************************************************** -->
2709 <!-- == inline_element -->
2713 name=
"u:bkslshEscPre"/>
2714 <xsl:text>:sub:`
</xsl:text>
2715 <xsl:apply-templates/>
2716 <xsl:text>`
</xsl:text>
2718 name=
"u:bkslshEscSuf"/>
2721 <!-- ******************************************************************** -->
2723 <!-- == inline_element -->
2725 match=
"superscript">
2727 name=
"u:bkslshEscPre"/>
2728 <xsl:text>:sup:`
</xsl:text>
2729 <xsl:apply-templates/>
2730 <xsl:text>`
</xsl:text>
2732 name=
"u:bkslshEscSuf"/>
2735 <!-- ******************************************************************** -->
2737 <!-- The target element has various roles depending on context; they are
2738 all handled here -->
2739 <!-- == simple_body_element == inline_element == directive -->
2744 test=
"name(preceding-sibling::*[1]) = 'reference'">
2745 <!-- An embedded inline target - handled by the reference itself -->
2748 test=
"contains($inline_containers, concat('*', name(..), '*'))">
2749 <!-- An inline target of some sort -->
2751 name=
"u:inlineReference">
2755 </xsl:call-template>
2759 <!-- An anonymous target directive -->
2761 name=
"u:outputClass"/>
2764 <xsl:text>__
</xsl:text>
2769 name=
"u:outputNamesRefid"/>
2770 <xsl:text>_
</xsl:text>
2781 test=
"@names | @refid">
2782 <!-- A target directive -->
2784 name=
"u:outputClass"/>
2787 <xsl:text>.. _
</xsl:text>
2792 name=
"u:outputNamesRefid"/>
2796 name=
"u:outputNames"/>
2799 <xsl:text>:
</xsl:text>
2802 <xsl:text> </xsl:text>
2809 <!-- Should not happen -->
2811 name=
"u:notSupported"/>
2816 <!-- ******************************************************************** -->
2819 Content Model: %text.model;
2821 <!-- == inline_element -->
2823 match=
"title_reference">
2825 name=
"u:bkslshEscPre"/>
2826 <xsl:text>`
</xsl:text>
2827 <xsl:apply-templates/>
2828 <xsl:text>`
</xsl:text>
2830 name=
"u:bkslshEscSuf"/>
2833 <!-- ******************************************************************** -->
2836 Content Model: %text.model;
2838 <!-- == inline_element -->
2841 <!-- TODO `role' directives must be generated for plain and derived
2842 user-defined roles. -->
2844 name=
"u:bkslshEscPre"/>
2845 <xsl:text>:
</xsl:text>
2848 <xsl:text>:`
</xsl:text>
2849 <xsl:apply-templates/>
2850 <xsl:text>`
</xsl:text>
2852 name=
"u:bkslshEscSuf"/>
2855 <!-- ******************************************************************** -->
2857 <!-- TODO `meta` directive must be implemented. -->
2859 <!-- ******************************************************************** -->
2862 Docutils wraps generated elements around text that is inserted (generated) by
2863 Docutils; i.e., text that was not in the document, like section numbers
2864 inserted by the "sectnum" directive.
2866 <!-- == inline_element -->
2870 <!-- == inline_element -->
2872 match=
"problematic">
2873 <!-- Simply output the contained text because this is probably the
2879 <!-- == compound_body_element -->
2881 match=
"system_message"/>
2883 <!-- ******************************************************************** -->
2884 <!-- ******************************************************************** -->
2887 When a block of text contains linefeeds, it was indented relative to a marker
2896 <!-- ******************************************************************** -->
2897 <!-- ******************************************************************** -->
2899 <!-- Add a blank line if necessary and indent -->
2908 <!-- ******************************************************************** -->
2910 <!-- Add a blank line in certain contexts -->
2913 <xsl:apply-templates
2914 mode=
"blankSkipInline"
2915 select=
"preceding::*[1]"/>
2918 <!-- Find the preceding element we are really interested in and act
2919 according to this element -->
2921 mode=
"blankSkipInline"
2924 <!-- Skip all inline elements and body subelements and check their
2927 test=
"contains(concat($inline_elements, $simple_body_subelements, $compound_body_subelements), concat('*', name(.), '*'))">
2928 <xsl:apply-templates
2929 mode=
"blankSkipInline"
2933 <!-- Reached the type of element we decide on -->
2935 test=
"contains($blank_after, concat('*', name(.), '*'))">
2942 <!-- ******************************************************************** -->
2945 Indent a block if it's a child of...
2978 <!-- This is only for `bullet_list/list_item';
2979 `enumerated_list/list_item' is handled special -->
2984 name=
"definition_list_item"
2990 name=
"option_list_item"
2992 <!-- This is also the indentation if block_quote comes as one of the
2993 special directives -->
2998 name=
"literal_block"
3008 <!-- Do indent according to ancestor -->
3011 <!-- In some cases the ancestors to indent for need to be determined
3012 by the calling template -->
3015 select=
"ancestor::*"/>
3017 select=
"$ancestors">
3023 test=
"contains($directives, concat('*', $this, '*'))">
3024 <!-- TODO Indentation of lines after some directives must be
3025 indented to align with the directive instead of a
3026 fixed indentation; however, this is rather complicated
3027 since identation for parameters should be fixed -->
3029 select=
"str:padding(3)"/>
3032 test=
"$this = 'list_item' and parent::enumerated_list">
3033 <!-- Enumerated list items base their indentation on the
3038 name=
"u:outputEnumerator"/>
3041 select=
"str:padding(string-length($enumerator))"/>
3045 select=
"str:padding(document('')//data:lookup/node[@name=$this]/@indent)"/>
3051 <!-- ******************************************************************** -->
3053 <!-- Indent a text containing line feeds correctly -->
3059 <!-- A fixed indentation may be given by caller -->
3062 <!-- If not given compute it -->
3068 test=
"contains($string,'
')">
3069 <!-- Output first physical line -->
3071 select=
"substring-before($string, '
')"/>
3073 <!-- Indent before the next line -->
3076 <!-- Output remaining physical lines -->
3081 select=
"substring-after($string, '
')"/>
3085 </xsl:call-template>
3087 <!-- String does not contain newline, so just output it -->
3095 <!-- ******************************************************************** -->
3097 <!-- Do output for those elements which do fold their inline content -->
3099 name=
"u:outputFolding">
3100 <!-- The prefix text to be output before the body -->
3104 <!-- The indentation for this body -->
3111 select=
"ancestor-or-self::*"/>
3112 </xsl:call-template>
3116 <!-- TODO Whitespace count of inline literals must be preserved -->
3117 <xsl:apply-templates/>
3119 <!-- Always output prefix with all trailing and leading spaces -->
3124 test=
"$fold > 0">
3127 select=
"normalize-space($string)"/>
3130 test=
"$string = ''">
3131 <!-- Empty strings need no output -->
3134 test=
"$normalized = ''">
3135 <!-- Only white-space in string; output a single space here -->
3139 <!-- Output leading white-space here -->
3141 test=
"normalize-space(substring($string, 1, 1)) = ''">
3145 name=
"u:indentFold">
3148 select=
"$normalized"/>
3154 select=
"string-length($indent) + string-length($prefix)"/>
3155 </xsl:call-template>
3156 <!-- Output trailing white-space here -->
3158 test=
"normalize-space(substring($string, string-length($string), 1)) = ''">
3172 <!-- ******************************************************************** -->
3174 <!-- Indent a string with folding -->
3176 name=
"u:indentFold">
3177 <!-- Normalized string to output -->
3180 <!-- Indentation to use for a new line -->
3183 <!-- Current output column -->
3184 <!-- TODO This is not a correct assumption for field definitions where
3185 the field name effectively determines the column of the first
3189 select=
"string-length($indent)"/>
3190 <!-- Do we start on a new (indented) line? -->
3197 <!-- TODO Quoted spaces must not end a word -->
3199 test=
"contains($string, ' ')">
3201 select=
"substring-before($string, ' ')"/>
3211 select=
"substring-after($string, ' ')"/>
3214 test=
"$string = ''"/>
3217 <!-- Output at least first word -->
3219 select=
"$firstWord"/>
3221 name=
"u:indentFold">
3230 select=
"$cursorColumn + string-length($firstWord)"/>
3234 </xsl:call-template>
3237 test=
"$cursorColumn + 1 + string-length($firstWord) > $fold">
3238 <!-- Line would get too long; start new line, indent and continue -->
3243 name=
"u:indentFold">
3252 select=
"string-length($indent)"/>
3256 </xsl:call-template>
3259 <!-- In a line and first word fits; separate and add word -->
3262 select=
"$firstWord"/>
3264 name=
"u:indentFold">
3273 select=
"$cursorColumn + 1 + string-length($firstWord)"/>
3277 </xsl:call-template>
3282 <!-- ******************************************************************** -->
3284 <!-- Output attributes of the current element as a field list -->
3290 <!-- Ancestors are needed for determining indentation; caller may give
3294 select=
"ancestor-or-self::*"/>
3297 <!-- Skip URIs based on parent -->
3299 test=
"name() != 'uri' and name() != 'xml:space'">
3304 select=
"$ancestors"/>
3305 </xsl:call-template>
3310 <!-- Output one attribute of the current element as a field list -->
3319 <!-- Ancestors are needed for determining indentation; caller may give
3323 select=
"ancestor::*"/>
3328 select=
"$ancestors"/>
3329 </xsl:call-template>
3330 <xsl:text>:
</xsl:text>
3333 test=
"$name = 'classes'">
3334 <xsl:text>class
</xsl:text>
3341 <xsl:text>:
</xsl:text>
3344 <xsl:text> </xsl:text>
3351 <!-- ******************************************************************** -->
3353 <!-- Output `\' or `\ ' before some inline element if necessary -->
3355 name=
"u:bkslshEscPre">
3356 <!-- Get the sibling node directly before the current element -->
3359 select=
"preceding-sibling::node()[1]"/>
3361 <!-- No sibling before this node -->
3363 test=
"not($before)"/>
3364 <!-- Element directly before this - must be another inline element -->
3366 test=
"name($before)">
3367 <!-- So separate it by a quoted space -->
3368 <xsl:text>\
</xsl:text>
3370 <!-- Node directly before this is text - check it -->
3372 test=
"not(contains(concat($apos, ' 
	
"([{<-/:'), substring($before, string-length($before), 1)))">
3373 <!-- Does not end in one of the allowed characters so separate it -->
3374 <xsl:text>\
</xsl:text>
3379 <!-- Output `\' after some inline element if necessary -->
3381 name=
"u:bkslshEscSuf">
3382 <!-- Get the sibling node directly after the current element -->
3385 select=
"following-sibling::node()[1]"/>
3387 <!-- No sibling after this node -->
3389 test=
"not($after)"/>
3390 <!-- Element directly after this - must be another inline element
3393 test=
"name($after)"/>
3394 <!-- Node directly after this is text - check it -->
3396 test=
"not(contains(concat($apos, ' 
	
")]}>-/:.,;!?\'), substring($after, 1, 1)))">
3397 <!-- Does not start with one of the allowed characters so separate
3399 <xsl:text>\
</xsl:text>
3404 <!-- ******************************************************************** -->
3407 name=
"u:notSupported">
3410 <xsl:text>######## NOT SUPPORTED: `
</xsl:text>
3413 <xsl:text>' ########
</xsl:text>
3417 <!-- ******************************************************************** -->
3421 <!-- Length of the rendered(!) text -->
3424 <!-- Depth 1 and 2 are document title and subtitle while depths
3425 greater than 2 are normal section titles -->
3428 <!-- Test whether a overline is wanted at all -->
3430 test=
"substring($adornment, 2 * ($depth - 1) + 1, 1) = 'o'">
3432 select=
"str:padding($length, substring($adornment, 2 * ($depth - 1) + 2, 1))"/>
3439 <!-- Length of the rendered(!) text -->
3442 <!-- Depth 1 and 2 are document title and subtitle while depths
3443 greater than 2 are normal section titles -->
3447 select=
"str:padding($length, substring($adornment, 2 * ($depth - 1) + 2, 1))"/>
3451 <!-- ******************************************************************** -->
3453 <!-- Output a non-standalone reference or target -->
3455 name=
"u:inlineReference">
3462 <!-- Is this a target instead of a reference? -->
3470 name=
"u:bkslshEscPre"/>
3471 <!-- Delimiter only if link contains other than alphanumerics -->
3475 test=
"* or translate($text, '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', '') or $embedded">
3476 <xsl:text>`
</xsl:text>
3481 <xsl:text>_
</xsl:text>
3484 select=
"$delimiter"/>
3485 <xsl:apply-templates
3489 <xsl:text> <</xsl:text>
3492 <xsl:text>></xsl:text>
3495 select=
"$delimiter"/>
3497 test=
"not($isTarget)">
3498 <xsl:text>_
</xsl:text>
3501 <xsl:text>_
</xsl:text>
3505 name=
"u:bkslshEscSuf"/>
3508 <!-- ******************************************************************** -->
3510 <!-- Output a class directive for the directly following element. -->
3511 <!-- TODO A class directive can also be used as a container putting the
3512 respective attribute to its content; however, this is not
3513 reflected in XML - you'd need to check a sequence of elements
3514 whether they all have the same attribute; furthermore class
3515 settings for block quotes needs to be treated special -->
3517 name=
"u:outputClass">
3518 <!-- Blank line already output? -->
3520 name=
"alreadyBlanked"
3522 <!-- Indentation already output? -->
3524 name=
"alreadyIndented"
3526 <!-- Add a blank line after class directive? -->
3533 test=
"not($alreadyBlanked)">
3538 test=
"not($alreadyIndented)">
3542 <xsl:text>.. class::
</xsl:text>
3553 <!-- ******************************************************************** -->
3555 <!-- Output a names attribute at index considering quoted spaces. -->
3557 name=
"u:outputNames">
3558 <!-- Blank line already output? -->
3566 select=
"str:replace(str:tokenize(normalize-space(str:replace($names, '\ ', '|')))[position() = $index + 1], '|', ' ')"/>
3569 <!-- ******************************************************************** -->
3571 <!-- Output a names attribute for a refid. -->
3573 name=
"u:outputNamesRefid">
3577 <!-- Determine the elements which is referred -->
3580 select=
"//*[@ids and math:max(dyn:map(str:tokenize(normalize-space(@ids)), 'number($refid = .)')) > 0]"/>
3582 name=
"u:outputNames">
3585 select=
"$refElem/@names"/>
3588 select=
"math:max(dyn:map(str:tokenize(normalize-space($refElem/@ids)), 'number($refid = .) * position() - 1'))"/>
3589 </xsl:call-template>
3592 <!-- ******************************************************************** -->
3593 <!-- ******************************************************************** -->
3595 <!-- Report unknown tags -->
3599 <xsl:text>`
</xsl:text>
3602 <xsl:text>' encountered
</xsl:text>
3605 <xsl:text> in `
</xsl:text>
3607 select=
"name(parent::*)"/>
3608 <xsl:text>'
</xsl:text>
3610 <xsl:text>, but no template matches.
</xsl:text>
3616 <!-- ********************************************************************** -->
3617 <!-- ********************************************************************** -->
3618 <!-- ********************************************************************** -->
3619 <!-- POD manual page
3623 xml2rst.xsl - An XSLT script to convert Docutils XML to reStructuredText
3627 xsltproc docutils.xml xml2rst.xsl
3631 B<xml2rst.xsl> is an XSLT script to convert Docutils XML to
3632 reStructuredText. You can use your favorite XSLT processor supporting
3633 EXSLT (e.g. xsltproc from the Gnome project) to generate
3634 reStructuredText from the Docutils intermediate XML representation.
3635 Its main use is to generate reStructuredText from some other format
3636 where a converter to Docutils XML already exists.
3640 The following options are supported. They are XSLT parameters for the
3641 whole script and must be given to the XSLT processor by the respective
3642 option (xsltproc: B<- -param> or B<- -stringparam>).
3648 Configures title markup to use so different styles can be requested
3651 The value of the parameter must be a string made up of a sequence of
3652 character pairs. The first character of a pair is C<o> (overline) or
3653 C<u> (underline) and the second character is the character to use for
3656 The first and the second character pair is used for document title and
3657 subtitle, the following pairs are used for section titles where the
3658 third pair is used for the top level section title.
3660 Defaults to C<o=o-u=u-u~u:u.u`>.
3664 Configures whether long text lines in paragraphs should be folded and
3665 to which length. This option is for input not coming from reST which
3666 may have no internal line feeds in plain text strings.
3668 If folding is enabled text strings not in a line feed preserving
3669 context are first white-space normalized and then broken according to
3670 the folding rules. Folding rules put out the first word and continue
3671 to do so with the following words unless the next word would cross
3672 the folding boundary. Words are delimited by white-space.
3674 Defaults to C<0>, i.e. no folding.
3678 =head2 Unsupported features
3680 It is generally not possible to create an exact reproduction of an
3681 original reStructuredText source from an intermediate XML file. The
3682 reason is that Docutils transports pretty much but not all information
3683 of the original source into the XML. Also the sequence is changed
3686 However, the coverage of Docutils features of B<xml2rst.xsl> is pretty
3687 good. A few minor features are not supported:
3691 =item * Fully minimized style for literal blocks
3693 =item * Substitution references for C<replace::> substitutions
3695 =item * Counting roman numbers in enumerated lists
3697 =item * Special table types like C<list-table::> and C<csv-table::>
3699 =item * Custom role definitions
3705 Installation is not necessary. Just use the file as downloaded with
3706 your favorite XSLT processor supporting EXSLT. For instance you can
3707 use B<xsltproc> from the Gnome project.
3711 Stefan Merten <smerten@oekonux.de> based on works by David Priest.
3715 This program is licensed under the terms of the GPL. See
3717 http://www.gnu.org/licenses/gpl.txt
3723 http://www.merten-home.de/FreeSoftware/xml2rst/