]> Lady’s Gitweb - Shrine-XSLT/blob - transform.xslt
0bd34a83758041a036fc0fca43a89aa7435197c5
[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="http://www.w3.org/1999/xhtml"
27 xmlns:exslt="http://exslt.org/common"
28 xmlns:html="http://www.w3.org/1999/xhtml"
29 xmlns:xslt="http://www.w3.org/1999/XSL/Transform"
30 version="1.0"
31 >
32 <xslt:variable name="source" select="current()"/>
33 <xslt:variable name="template" select="document('./template.xml')"/>
34
35 <!--
36 Instead of actually processing the root node, process the template in `template` mode.
37 -->
38 <xslt:template match="/">
39 <xslt:apply-templates select="exslt:node-set($template)" mode="template"/>
40 </xslt:template>
41
42 <!--
43 Process non‐template elements.
44 By default, just copy the element, but remove any `@data-shrine-*` attribuets or `@slot` attributes with a value that begins with `shrine-`.
45 -->
46 <xslt:template match="*|text()" mode="content">
47 <xslt:copy>
48 <xslt:for-each select="@*[not(starts-with(name(), 'data-shrine-')) and not(name()='slot' and starts-with(., 'shrine-'))]">
49 <xslt:copy/>
50 </xslt:for-each>
51 <xslt:for-each select="*|text()">
52 <xslt:choose>
53 <xslt:when test="@slot[starts-with(., 'shrine-')]">
54 <xslt:comment>
55 <text> placeholder for slotted element </text>
56 </xslt:comment>
57 </xslt:when>
58 <xslt:otherwise>
59 <xslt:apply-templates select="." mode="content"/>
60 </xslt:otherwise>
61 </xslt:choose>
62 </xslt:for-each>
63 </xslt:copy>
64 </xslt:template>
65
66 <!--
67 Process template elements.
68 By default, just copy the element.
69 This behaviour will be overridden for certain elements to insert the page content.
70 -->
71 <xslt:template match="*|text()" mode="template">
72 <xslt:copy>
73 <xslt:for-each select="@*">
74 <xslt:copy/>
75 </xslt:for-each>
76 <xslt:apply-templates mode="template"/>
77 </xslt:copy>
78 </xslt:template>
79
80 <!--
81 Process the template `<html>`.
82 This copies over `@lang` and non‐shrine `@data-*` attributes from the root node.
83 -->
84 <xslt:template match="html:html" mode="template">
85 <xslt:copy>
86 <xslt:for-each select="@*">
87 <xslt:copy/>
88 </xslt:for-each>
89 <xslt:for-each select="exslt:node-set($source)/*/@*[name()='lang' or name()='xml:lang' or starts-with(name(), 'data-') and not(starts-with(name(), 'data-shrine-'))]">
90 <xslt:if test="not(exslt:node-set($template)/*/@*[name()=name(current())])">
91 <xslt:copy/>
92 </xslt:if>
93 </xslt:for-each>
94 <xslt:apply-templates mode="template"/>
95 </xslt:copy>
96 </xslt:template>
97
98 <!--
99 Process the template `<head>`.
100 This inserts appropriate metadata based on the document.
101 -->
102 <xslt:template match="html:head" mode="template">
103 <xslt:copy>
104 <xslt:for-each select="@*">
105 <xslt:copy/>
106 </xslt:for-each>
107 <xslt:for-each select="exslt:node-set($source)//*[@slot='shrine-head']">
108 <xslt:text>&#x0A;</xslt:text>
109 <xslt:apply-templates select="." mode="content"/>
110 </xslt:for-each>
111 <xslt:if test="not(exslt:node-set($source)//html:title[@slot='shrine-head'])">
112 <xslt:text>&#x0A;</xslt:text>
113 <title>
114 <xslt:apply-templates select="exslt:node-set($source)//html:h1" mode="text"/>
115 </title>
116 </xslt:if>
117 <xslt:apply-templates mode="template"/>
118 </xslt:copy>
119 </xslt:template>
120
121 <!--
122 Process the template header.
123 Read the `@data-header` attribute of the root element, append `"-header.xml"` to the end of it, and process the resulting document.
124 If no `@data-header` attribute is provided, no header is rendered.
125 -->
126 <xslt:template match="html:shrine-header" mode="template">
127 <xslt:for-each select="exslt:node-set($source)/*/@data-shrine-header">
128 <xslt:apply-templates select="document(concat('./', ., '-header.xml'), $template)/*" mode="content"/>
129 </xslt:for-each>
130 </xslt:template>
131
132 <!--
133 Process the template footer.
134 Read the `@data-footer` attribute of the root element, append `"-footer.xml"` to the end of it, and process the resulting document.
135 If no `@data-footer` attribute is provided, no footer is rendered.
136 -->
137 <xslt:template match="html:shrine-footer" mode="template">
138 <xslt:for-each select="exslt:node-set($source)/*/@data-shrine-footer">
139 <xslt:apply-templates select="document(concat('./', ., '-footer.xml'), $template)/*" mode="content"/>
140 </xslt:for-each>
141 </xslt:template>
142
143 <!--
144 Process the content.
145 -->
146 <xslt:template match="html:shrine-content" mode="template">
147 <xslt:apply-templates select="exslt:node-set($source)/*" mode="content"/>
148 </xslt:template>
149
150 <!--
151 Provide the complete text content of the provided element.
152 -->
153 <xslt:template match="*|text()" mode="text">
154 <xslt:choose>
155 <xslt:when test="self::*">
156 <xslt:apply-templates mode="text"/>
157 </xslt:when>
158 <xslt:when test="self::text()">
159 <xslt:copy/>
160 </xslt:when>
161 </xslt:choose>
162 </xslt:template>
163 </xslt:transform>
This page took 0.050964 seconds and 3 git commands to generate.