]> Lady’s Gitweb - Shrine-XSLT/blob - transform.xslt
Change output mode to H·T·M·L
[Shrine-XSLT] / transform.xslt
1 <!--
2 This is an extremely simple XSLT transform which simply reads in a
3 `template.xml` and :—
4
5 • Replaces the `<html:shrine-content>` element with the content of the document it is being applied to,
6
7 • If the root element of the document it is being applied to has a `@data-shrine-header` attribute, replaces the `<html:shrine-header>` with the contents of the corresponding header file (`⸺-header.xml`), and
8
9 • If the root element of the document it is being applied to has a `@data-shrine-footer` attribute, replaces the `<html:shrine-footer>` with the contents of the corresponding footer file (`⸺-footer.xml`), and
10
11 • Copies any remaining `@lang` or `@data-*` attributes from the root element of the document it is being applied to over to the root element of the template.
12
13 The intent is that this file is used in conjunction with a Makefile to quickly automate inserting header and footer content into documents.
14 The exact feature·set might be somewhat more expansive than the description above; for a lengthier overview of what this file does, see `README.markdown`.
15
16 Feel free to add additional templates and features to suit your needs!
17
18 ___
19
20 © 2022 Lady [@ Lady’s Computer]
21
22 This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
23 If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
24 -->
25 <xslt:transform
26 xmlns:html="http://www.w3.org/1999/xhtml"
27 xmlns:xslt="http://www.w3.org/1999/XSL/Transform"
28 version="1.0"
29 >
30 <xslt:variable name="source" select="current()"/>
31 <xslt:variable name="template" select="document('./template.xml')"/>
32
33 <!--
34 Instead of actually processing the root node, process the template in `template` mode.
35 -->
36 <xslt:template match="/">
37 <xslt:apply-templates select="$template" mode="template"/>
38 </xslt:template>
39
40 <!--
41 Process non‐template elements.
42 By default, just copy the element, but remove any `@data-shrine-*` attribuets or `@slot` attributes with a value that begins with `shrine-`.
43 Some elements may have special treatment.
44 -->
45 <xslt:template match="*" mode="content">
46 <xslt:element name="{local-name()}">
47 <xslt:for-each select="@*[not(starts-with(name(), 'data-shrine-')) and not(name()='slot' and starts-with(., 'shrine-'))]">
48 <xslt:copy/>
49 </xslt:for-each>
50 <xslt:for-each select="*|text()">
51 <xslt:choose>
52 <xslt:when test="@slot[starts-with(., 'shrine-')]">
53 <xslt:comment>
54 <text> placeholder for slotted element </text>
55 </xslt:comment>
56 </xslt:when>
57 <xslt:otherwise>
58 <xslt:apply-templates select="." mode="content"/>
59 </xslt:otherwise>
60 </xslt:choose>
61 </xslt:for-each>
62 </xslt:element>
63 </xslt:template>
64
65 <!--
66 Process text content; just make a copy.
67 -->
68 <xslt:template match="text()" mode="content">
69 <xslt:copy/>
70 </xslt:template>
71
72 <!--
73 Process template elements.
74 By default, just copy the element.
75 This behaviour will be overridden for certain elements to insert the page content.
76 -->
77 <xslt:template match="*" mode="template">
78 <xslt:element name="{local-name()}">
79 <xslt:for-each select="@*">
80 <xslt:copy/>
81 </xslt:for-each>
82 <xslt:apply-templates mode="template"/>
83 </xslt:element>
84 </xslt:template>
85
86 <!--
87 Process template text; just make a copy.
88 -->
89 <xslt:template match="text()" mode="content">
90 <xslt:copy/>
91 </xslt:template>
92
93 <!--
94 Process the template `<html>` elements.
95 This copies over `@lang` and non‐shrine `@data-*` attributes from the root node.
96 -->
97 <xslt:template match="html:html" mode="template">
98 <html>
99 <xslt:for-each select="@*[not(starts-with(name(), 'xmlns'))]">
100 <xslt:copy/>
101 </xslt:for-each>
102 <xslt:for-each select="$source/*/@*[name()='lang' or starts-with(name(), 'data-') and not(starts-with(name(), 'data-shrine-'))]">
103 <xslt:if test="not($template/*/@*[name()=name(current())])">
104 <xslt:copy/>
105 </xslt:if>
106 </xslt:for-each>
107 <xslt:apply-templates mode="template"/>
108 </html>
109 </xslt:template>
110
111 <!--
112 Process the template `<head>` elements.
113 This inserts appropriate metadata based on the document.
114 -->
115 <xslt:template match="html:head" mode="template">
116 <head>
117 <xslt:for-each select="@*">
118 <xslt:copy/>
119 </xslt:for-each>
120 <xslt:if test="not($source//html:title[@slot='shrine-head'])">
121 <title>
122 <xslt:apply-templates select="$source//html:h1" mode="text"/>
123 </title>
124 </xslt:if>
125 <xslt:apply-templates mode="template"/>
126 <xslt:for-each select="$source//*[@slot='shrine-head']">
127 <xslt:apply-templates select="." mode="content"/>
128 </xslt:for-each>
129 </head>
130 </xslt:template>
131
132 <!--
133 Process the template header.
134 Read the `@data-header` attribute of the root element, append `"-header.xml"` to the end of it, and process the resulting document.
135 If no `@data-header` attribute is provided, no header is rendered.
136 -->
137 <xslt:template match="html:shrine-header" mode="template">
138 <xslt:for-each select="$source/*/@data-shrine-header">
139 <xslt:apply-templates select="document(concat('./', ., '-header.xml'), $template)/*" mode="content"/>
140 </xslt:for-each>
141 </xslt:template>
142
143 <!--
144 Process the template footer.
145 Read the `@data-footer` attribute of the root element, append `"-footer.xml"` to the end of it, and process the resulting document.
146 If no `@data-footer` attribute is provided, no footer is rendered.
147 -->
148 <xslt:template match="html:shrine-footer" mode="template">
149 <xslt:for-each select="$source/*/@data-shrine-footer">
150 <xslt:apply-templates select="document(concat('./', ., '-footer.xml'), $template)/*" mode="content"/>
151 </xslt:for-each>
152 </xslt:template>
153
154 <!--
155 Process the content.
156 -->
157 <xslt:template match="html:shrine-content" mode="template">
158 <xslt:apply-templates select="$source/*" mode="content"/>
159 </xslt:template>
160
161 <!--
162 Provide the complete text content of the provided element.
163 -->
164 <xslt:template match="*|text()" mode="text">
165 <xslt:choose>
166 <xslt:when test="self::*">
167 <xslt:apply-templates mode="text"/>
168 </xslt:when>
169 <xslt:when test="self::text()">
170 <xslt:copy/>
171 </xslt:when>
172 </xslt:choose>
173 </xslt:template>
174
175 <!--
176 Set the output mode to HTML.
177 -->
178 <xslt:output method="html" charset="UTF-8" doctype-system="about:legacy-compat" indent="no"/>
179 </xslt:transform>
This page took 0.112444 seconds and 5 git commands to generate.