]> Lady’s Gitweb - Shushe/blob - lib/expandmetadata.xslt
Support “soft” dependencies
[Shushe] / lib / expandmetadata.xslt
1 <?xml version="1.0"?>
2 <!--
3 SPDX-FileCopyrightText: 2023, 2024, 2025 Lady <https://www.ladys.computer/about/#lady>
4 SPDX-License-Identifier: MPL-2.0
5 -->
6 <!--
7 ⁌ ⛩📰 书社 ∷ lib/expandmetadata.xslt
8
9 © 2023–2025 Lady [@ Ladys Computer].
10
11 This Source Code Form is subject to the terms of the Mozilla Public License, v 2.0.
12 If a copy of the M·P·L was not distributed with this file, You can obtain one at <https://mozilla.org/MPL/2.0/>.
13 -->
14 <transform
15 xmlns="http://www.w3.org/1999/XSL/Transform"
16 xmlns:exsl="http://exslt.org/common"
17 xmlns:exslstr="http://exslt.org/strings"
18 xmlns:nie="http://www.semanticdesktop.org/ontologies/2007/01/19/nie#"
19 xmlns:nfo="http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#"
20 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
21 xmlns:xlink="http://www.w3.org/1999/xlink"
22 xmlns:书社="urn:fdc:ladys.computer:20231231:Shu1She4"
23 xmlns:书社vocab="urn:fdc:ladys.computer:20231231:Shu1She4:vocab:"
24 extension-element-prefixes="exsl exslstr"
25 version="1.0"
26 >
27 <variable name="builddir" select="//书社vocab:BuildDirectory/@nfo:fileUrl"/>
28 <variable name="files" select="//书社vocab:SourceFile|//书社vocab:IncludeFile"/>
29 <variable name="stated-dependencies-fragment">
30 <for-each select="$files[nie:interpretedAs/nfo:PlainTextDocument]">
31 <variable name="uri" select="书社vocab:hasParsedFile/@nfo:fileUrl"/>
32 <书社:Dependencies for="{@rdf:about}">
33 <for-each select="document($uri)//书社:link">
34 <variable name="spaced-show">
35 <choose>
36 <when test="@xlink:show">
37 <text> </text>
38 <value-of select="@xlink:show"/>
39 <text> </text>
40 </when>
41 <otherwise>
42 <text> none </text>
43 </otherwise>
44 </choose>
45 </variable>
46 <variable name="actuate">
47 <choose>
48 <when test="@xlink:actuate">
49 <value-of select="@xlink:actuate"/>
50 </when>
51 <otherwise>
52 <text>none</text><!-- not the true default in all cases, but in the ones that matter -->
53 </otherwise>
54 </choose>
55 </variable>
56 <variable name="name" select="string(@name)"/>
57 <if test="contains(' embed other none ', $spaced-show) and $actuate='none'">
58 <variable name="identifier" select="string(@xlink:href)"/>
59 <variable name="is-dir" select="substring($identifier, string-length($identifier))='/'"/>
60 <for-each select="$files/@rdf:about[string(.)=$identifier or $is-dir and starts-with(., $identifier)]">
61 <sort select="." data-type="text" lang="zxx" case-order="upper-first"/>
62 <choose>
63 <when test="$spaced-show=' embed '">
64 <书社:dependency name="{$name}">
65 <value-of select="."/>
66 </书社:dependency>
67 </when>
68 <when test="$spaced-show=' other '">
69 <书社:transitive-soft-dependency name="{$name}">
70 <value-of select="."/>
71 </书社:transitive-soft-dependency>
72 </when>
73 <otherwise>
74 <书社:soft-dependency name="{$name}">
75 <value-of select="."/>
76 </书社:soft-dependency>
77 </otherwise>
78 </choose>
79 </for-each>
80 </if>
81 </for-each>
82 </书社:Dependencies>
83 </for-each>
84 </variable>
85 <variable name="stated-dependencies" select="exsl:node-set($stated-dependencies-fragment)/*"/>
86 <template name="书社:collect-dependency-paths">
87 <param name="path" select="/.."/>
88 <variable name="parent" select="$path/*[last()]"/>
89 <variable name="children-fragment">
90 <for-each select="$stated-dependencies[@for=string($parent)]/*">
91 <choose>
92 <when test="$path/*[string()=current()]">
93 <if test="self::书社:dependency">
94 <书社:recursive-dependency name="{@name}">
95 <value-of select="."/>
96 </书社:recursive-dependency>
97 </if>
98 </when>
99 <otherwise>
100 <copy-of select="."/>
101 </otherwise>
102 </choose>
103 </for-each>
104 </variable>
105 <variable name="children" select="exsl:node-set($children-fragment)/*"/>
106 <variable name="child-paths-fragment">
107 <for-each select="$children">
108 <choose>
109 <when test="self::书社:recursive-dependency">
110 <书社:dependency-path>
111 <copy-of select="$path/*[string()=current()][1]/preceding-sibling::*"/>
112 <copy-of select="."/><!-- replace first instance with recursive dependency -->
113 </书社:dependency-path>
114 </when>
115 <when test="$parent/self::书社:transitive-soft-dependency and string(@name)!=string($parent/@name)"/>
116 <when test="self::书社:soft-dependency">
117 <书社:dependency-path>
118 <copy-of select="$path"/>
119 <copy-of select="."/>
120 </书社:dependency-path>
121 </when>
122 <otherwise>
123 <variable name="path-fragment">
124 <copy-of select="$path"/>
125 <choose>
126 <when test="self::书社:dependency and $path/书社:transitive-soft-dependency">
127 <书社:transitive-soft-dependency name="{@name}">
128 <value-of select="."/>
129 </书社:transitive-soft-dependency>
130 </when>
131 <otherwise>
132 <copy-of select="."/>
133 </otherwise>
134 </choose>
135 </variable>
136 <call-template name="书社:collect-dependency-paths">
137 <with-param name="path" select="exsl:node-set($path-fragment)"/>
138 </call-template><!-- a little inefficient in the case of reflexive dependencies, as the path will be traversed once in each direction, but improving on this is a hard problem in X·S·L·T -->
139 </otherwise>
140 </choose>
141 </for-each>
142 </variable>
143 <variable name="child-paths" select="exsl:node-set($child-paths-fragment)/*"/>
144 <choose>
145 <when test="$child-paths">
146 <copy-of select="$child-paths"/>
147 </when>
148 <otherwise><!-- fallback result is just the input path -->
149 <书社:dependency-path>
150 <copy-of select="$path"/>
151 </书社:dependency-path>
152 </otherwise>
153 </choose>
154 </template>
155 <template match="nie:interpretedAs/*" priority="1">
156 <copy>
157 <apply-templates select="@*|node()"/>
158 <for-each select="../../书社vocab:hasParsedFileWithMetadata">
159 <copy-of select="document(@nfo:fileUrl)/书社:parsed/书社:metadata/rdf:RDF/rdf:Description/node()"/>
160 </for-each>
161 </copy>
162 </template>
163 <template match="//书社vocab:SourceFile[not(nie:interpretedAs/nfo:PlainTextDocument)]" priority="1">
164 <copy>
165 <apply-templates select="@*"/>
166 <apply-templates select="node()"/>
167 <element name="书社vocab:destination">
168 <value-of select="@书社vocab:path"/>
169 </element>
170 </copy>
171 </template>
172 <template match="//书社vocab:SourceFile[nie:interpretedAs/nfo:PlainTextDocument]" priority="1">
173 <variable name="parsed" select="document(书社vocab:hasParsedFile/@nfo:fileUrl)"/>
174 <variable name="provided-destinations" select="normalize-space($parsed/*/@书社:destination)"/>
175 <variable name="destinations-fragment">
176 <if test="$provided-destinations!=''">
177 <for-each select="exslstr:tokenize($provided-destinations)">
178 <element name="书社vocab:destination">
179 <value-of select="."/>
180 </element>
181 </for-each>
182 </if>
183 </variable>
184 <variable name="destinations" select="exsl:node-set($destinations-fragment)/node()"/>
185 <variable name="bad-destinations-fragment">
186 <for-each select="$destinations">
187 <variable name="destination-delim" select="concat('/', ., '/')"/>
188 <if test="contains($destination-delim, '//') or contains($destination-delim, '/./') or contains($destination-delim, '/../')">
189 <copy-of select="."/>
190 </if>
191 </for-each>
192 </variable>
193 <variable name="bad-destinations" select="exsl:node-set($bad-destinations-fragment)/node()"/>
194 <copy>
195 <apply-templates select="@*"/>
196 <apply-templates select="node()"/>
197 <apply-templates select="." mode="书社:dependencies"/>
198 <choose>
199 <when test="not($destinations)">
200 <element name="书社vocab:destination">
201 <value-of select="@书社vocab:path"/>
202 </element>
203 </when>
204 <when test="$bad-destinations">
205 <message terminate="no">
206 <text>Bad destinations: </text>
207 <for-each select="$bad-destinations">
208 <if test="position()>1">
209 <text> </text>
210 </if>
211 <text>&lt;</text>
212 <value-of select="."/>
213 <text>></text>
214 </for-each>
215 </message>
216 <element name="书社vocab:destination">
217 <value-of select="@书社vocab:path"/>
218 </element>
219 </when>
220 <otherwise>
221 <for-each select="$destinations">
222 <element name="书社vocab:destination">
223 <value-of select="."/>
224 </element>
225 </for-each>
226 </otherwise>
227 </choose>
228 </copy>
229 </template>
230 <template match="//书社vocab:IncludeFile[nie:interpretedAs/nfo:PlainTextDocument]" priority="1">
231 <copy>
232 <apply-templates select="@*|node()"/>
233 <apply-templates select="." mode="书社:dependencies"/>
234 </copy>
235 </template>
236 <template match="书社vocab:hasParsedFileWithMetadata" priority="1"/>
237 <template match="/">
238 <variable name="result-fragment">
239 <apply-templates/>
240 </variable>
241 <variable name="result" select="exsl:node-set($result-fragment)"/>
242 <copy-of select="$result/*"/>
243 <exsl:document href="dependencies" method="text" encoding="UTF-8">
244 <for-each select="$result/rdf:RDF/*[nie:interpretedAs/nfo:PlainTextDocument]">
245 <value-of select="@rdf:about"/>
246 <text>&#xA;</text>
247 <for-each select="书社vocab:hasRecursiveDependencyOn/@rdf:resource">
248 <text>&#x9;-</text>
249 <value-of select="."/>
250 <text>&#xA;</text>
251 </for-each>
252 <for-each select="书社vocab:hasSoftDependencyOn/@rdf:resource">
253 <text>&#x9;?</text>
254 <value-of select="."/>
255 <text>&#xA;</text>
256 </for-each>
257 <for-each select="书社vocab:hasDependencyOn/@rdf:resource">
258 <text>&#x9;</text>
259 <value-of select="."/>
260 <text>&#xA;</text>
261 </for-each>
262 </for-each>
263 </exsl:document>
264 <exsl:document href="destinations" method="text" encoding="UTF-8">
265 <for-each select="$result//书社vocab:SourceFile">
266 <value-of select="@rdf:about"/>
267 <text>|</text>
268 <for-each select="书社vocab:destination">
269 <if test="position()>1">
270 <text>;</text>
271 </if>
272 <value-of select="."/>
273 </for-each>
274 <text>&#xA;</text>
275 </for-each>
276 </exsl:document>
277 </template>
278 <template match="@*|node()">
279 <copy>
280 <apply-templates select="@*|node()"/>
281 </copy>
282 </template>
283 <template match="书社vocab:SourceFile|书社vocab:IncludeFile" mode="书社:dependencies">
284 <if test="nie:interpretedAs/nfo:PlainTextDocument">
285 <variable name="path-fragment">
286 <element name="书社:dependency-root">
287 <value-of select="@rdf:about"/>
288 </element>
289 </variable>
290 <variable name="paths-fragment">
291 <call-template name="书社:collect-dependency-paths">
292 <with-param name="path" select="exsl:node-set($path-fragment)"/>
293 </call-template>
294 </variable>
295 <variable name="paths-document" select="exsl:node-set($paths-fragment)"/>
296 <for-each select="$paths-document//书社:recursive-dependency">
297 <if test="not(preceding::*[string()=string(current())])">
298 <element name="书社vocab:hasRecursiveDependencyOn">
299 <attribute name="rdf:resource">
300 <value-of select="."/>
301 </attribute>
302 </element>
303 </if>
304 </for-each>
305 <for-each select="$paths-document//书社:dependency">
306 <if test="not((preceding::*|//书社:recursive-dependency)[string()=string(current())])">
307 <element name="书社vocab:hasDependencyOn">
308 <attribute name="rdf:resource">
309 <value-of select="."/>
310 </attribute>
311 </element>
312 </if>
313 </for-each>
314 <for-each select="$paths-document//*[self::书社:soft-dependency or self::书社:transitive-soft-dependency]">
315 <if test="not((preceding::*|//书社:recursive-dependency|//书社:dependency)[string()=string(current())])">
316 <element name="书社vocab:hasSoftDependencyOn">
317 <attribute name="rdf:resource">
318 <value-of select="."/>
319 </attribute>
320 </element>
321 </if>
322 </for-each>
323 </if>
324 </template>
325 <output method="xml" encoding="UTF-8"/>
326 </transform>
This page took 0.066355 seconds and 5 git commands to generate.