]> Lady’s Gitweb - Vocab/blob - transforms/infer.xslt
Support disjoint unions; improve modelling somewhat
[Vocab] / transforms / infer.xslt
1 <?xml version="1.0"?>
2 <!--
3 SPDX-FileCopyrightText: 2024, 2025 Lady <https://www.ladys.computer/about/#lady>
4 SPDX-License-Identifier: MPL-2.0
5 -->
6 <!--
7 © 2024–2025 Lady [@ Ladys Computer].
8
9 This Source Code Form is subject to the terms of the Mozilla Public License, v 2.0.
10 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/>.
11 -->
12 <transform
13 xmlns="http://www.w3.org/1999/XSL/Transform"
14 xmlns:Vocab="urn:fdc:vocab.ladys.computer:20240731:ns"
15 xmlns:Vocabvocab="urn:fdc:vocab.ladys.computer:20240731:vocab:"
16 xmlns:exsl="http://exslt.org/common"
17 xmlns:exslfunc="http://exslt.org/functions"
18 xmlns:owl="http://www.w3.org/2002/07/owl#"
19 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
20 xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
21 xmlns:书社="urn:fdc:ladys.computer:20231231:Shu1She4"
22 exclude-result-prefixes="Vocab Vocabvocab"
23 extension-element-prefixes="exsl exslfunc"
24 version="1.0"
25 >
26 <书社:id>urn:fdc:vocab.ladys.computer:20240731:transforms:infer.xslt</书社:id>
27 <key name="Vocab:equivalent-class" match="owl:Class|owl:Restriction|rdfs:Datatype" use="owl:equivalentClass/@rdf:resource"/>
28 <key name="Vocab:equivalent-property" match="owl:AnnotationProperty|owl:DatatypeProperty|owl:ObjectProperty" use="owl:equivalentProperty/@rdf:resource"/>
29 <key name="Vocab:equivalent-individual" match="owl:NamedIndividual" use="owl:sameAs/@rdf:resource"/>
30 <key name="Vocab:inverse-class" match="owl:Class|rdfs:Datatype" use="owl:complementOf/@rdf:resource"/>
31 <key name="Vocab:inverse-property" match="owl:DatatypeProperty|owl:ObjectProperty" use="owl:inverseOf/@rdf:resource"/>
32 <key name="Vocab:disjoint-class" match="owl:Class|rdfs:Datatype" use="owl:disjointWith/@rdf:resource"/>
33 <key name="Vocab:disjoint-class-union" match="owl:Class" use="owl:disjointUnionOf/rdf:Description/@rdf:about"/>
34 <key name="Vocab:disjoint-property" match="owl:DatatypeProperty|owl:ObjectProperty" use="owl:propertyDisjointWith/@rdf:resource"/>
35 <exslfunc:function name="Vocab:get-equivalents">
36 <param name="resource-nodes"/>
37 <param name="kind" select="'individual'"/>
38 <param name="include-self" select="false()"/>
39 <param name="exclude" select="/.."/>
40 <variable name="result-fragment">
41 <call-template name="Vocab:get-fragment-of-equivalents">
42 <with-param name="kind" select="$kind"/>
43 <with-param name="resource-nodes" select="$resource-nodes"/>
44 <with-param name="include-self" select="$include-self"/>
45 <with-param name="exclude" select="$exclude"/>
46 </call-template>
47 </variable>
48 <exslfunc:result select="exsl:node-set($result-fragment)/*"/>
49 </exslfunc:function>
50 <exslfunc:function name="Vocab:get-transitives">
51 <param name="resource-nodes"/>
52 <param name="kind" select="'individual'"/>
53 <param name="relationship"/>
54 <param name="include-self" select="false()"/>
55 <param name="exclude" select="/.."/>
56 <variable name="result-fragment">
57 <call-template name="Vocab:get-fragment-of-transitives">
58 <with-param name="kind" select="$kind"/>
59 <with-param name="relationship" select="$relationship"/>
60 <with-param name="resource-nodes" select="$resource-nodes"/>
61 <with-param name="include-self" select="$include-self"/>
62 <with-param name="exclude" select="$exclude"/>
63 </call-template>
64 </variable>
65 <exslfunc:result select="exsl:node-set($result-fragment)/*"/>
66 </exslfunc:function>
67 <exslfunc:function name="Vocab:get-symmetrics">
68 <param name="resource-nodes"/>
69 <param name="kind"/>
70 <param name="relationship"/>
71 <param name="include-self" select="false()"/>
72 <param name="exclude" select="/.."/>
73 <variable name="root" select="/"/>
74 <variable name="relationship-names" select="Vocab:relationship-names($kind, $relationship)"/>
75 <variable name="result-fragment">
76 <if test="string($relationship-names/Vocab:local-name)!=''">
77 <variable name="relationship-key">
78 <text>Vocab:</text>
79 <value-of select="$relationship"/>
80 <text>-</text>
81 <value-of select="$kind"/>
82 </variable>
83 <variable name="equivalents" select="Vocab:get-equivalents($resource-nodes, $kind, true(), $exclude)"/>
84 <variable name="unfiltered-result-fragment">
85 <if test="$include-self">
86 <copy-of select="$equivalents"/>
87 </if>
88 <for-each select="$equivalents/@rdf:about">
89 <variable name="source" select="string()"/>
90 <for-each select="$root">
91 <for-each select="key(concat('Vocab:named-', $kind), $source)">
92 <apply-templates select="*[local-name()=$relationship-names/Vocab:local-name and namespace-uri()=$relationship-names/Vocab:namespace]" mode="Vocab:format-get">
93 <with-param name="source" select="$source"/>
94 </apply-templates>
95 </for-each>
96 <for-each select="key($relationship-key, $source)[@rdf:about]">
97 <apply-templates select="." mode="Vocab:format-get">
98 <with-param name="source" select="string(@rdf:about)"/>
99 </apply-templates>
100 </for-each>
101 <if test="$relationship-names/Vocab:in-union">
102 <for-each select="key(concat($relationship-key, '-union'), $source)">
103 <apply-templates select="*[local-name()=$relationship-names/Vocab:in-union/Vocab:local-name and namespace-uri()=$relationship-names/Vocab:in-union/Vocab:namespace]/*" mode="Vocab:format-get">
104 <with-param name="source" select="string(@rdf:about)"/>
105 </apply-templates>
106 </for-each>
107 </if>
108 </for-each>
109 </for-each>
110 </variable>
111 <variable name="filter-fragment">
112 <copy-of select="$exclude"/>
113 <if test="not($include-self)">
114 <copy-of select="$equivalents"/>
115 </if>
116 </variable>
117 <for-each select="exsl:node-set($unfiltered-result-fragment)/*">
118 <copy-of select="self::*[not(@rdf:about and (exsl:node-set($filter-fragment)/*|preceding-sibling::*)/@rdf:about[string()=string(current()/@rdf:about)])]"/>
119 </for-each>
120 </if>
121 </variable>
122 <exslfunc:result select="exsl:node-set($result-fragment)/*"/>
123 </exslfunc:function>
124 <exslfunc:function name="Vocab:relationship-names">
125 <param name="kind"/>
126 <param name="relationship"/>
127 <variable name="result-fragment">
128 <element name="Vocab:local-name">
129 <choose>
130 <when test="$relationship='equivalent' and $kind='class'">
131 <text>equivalentClass</text>
132 </when>
133 <when test="$relationship='equivalent' and $kind='property'">
134 <text>equivalentProperty</text>
135 </when>
136 <when test="$relationship='equivalent' and $kind='individual'">
137 <text>sameAs</text>
138 </when>
139 <when test="$relationship='super' and $kind='class'">
140 <text>subClassOf</text>
141 </when>
142 <when test="$relationship='super' and $kind='property'">
143 <text>subPropertyOf</text>
144 </when>
145 <when test="$relationship='inverse' and $kind='class'">
146 <text>complementOf</text>
147 </when>
148 <when test="$relationship='inverse' and $kind='property'">
149 <text>inverseOf</text>
150 </when>
151 <when test="$relationship='disjoint' and $kind='class'">
152 <text>disjointWith</text>
153 </when>
154 <when test="$relationship='disjoint' and $kind='property'">
155 <text>propertyDisjointWith</text>
156 </when>
157 </choose>
158 </element>
159 <element name="Vocab:namespace">
160 <choose>
161 <when test="$relationship='super'">
162 <text>http://www.w3.org/2000/01/rdf-schema#</text>
163 </when>
164 <otherwise>
165 <text>http://www.w3.org/2002/07/owl#</text>
166 </otherwise>
167 </choose>
168 </element>
169 <if test="$relationship='disjoint' and $kind='class'">
170 <element name="Vocab:in-union">
171 <element name="Vocab:local-name">
172 <text>disjointUnionOf</text>
173 </element>
174 <element name="Vocab:namespace">
175 <text>http://www.w3.org/2002/07/owl#</text>
176 </element>
177 </element>
178 </if>
179 </variable>
180 <exslfunc:result select="exsl:node-set($result-fragment)"/>
181 </exslfunc:function>
182 <template name="Vocab:get-fragment-of-equivalents">
183 <param name="kind" select="'individual'"/>
184 <param name="resource-nodes" select="/.."/> <!-- not yet processed, but selected -->
185 <param name="include-self" select="true()"/> <!-- make false on first run to not include provided nodes -->
186 <param name="exclude" select="/.."/> <!-- leave named nodes out of result -->
187 <param name="gotten" select="/.."/> <!-- already processed -->
188 <variable name="root" select="/"/>
189 <variable name="relationship-names" select="Vocab:relationship-names($kind, 'equivalent')"/>
190 <variable name="gotten-nodes" select="exsl:node-set($gotten)/*"/>
191 <variable name="next"> <!-- new selection -->
192 <for-each select="$resource-nodes/@rdf:about">
193 <!-- Iterate over each named resource to get, find it, and get the equivalent resources. -->
194 <if test="not(($gotten-nodes|../preceding-sibling::*)/@rdf:about[string()=string(current())])">
195 <variable name="source" select="string()"/>
196 <for-each select="$root">
197 <for-each select="key(concat('Vocab:named-', $kind), $source)">
198 <apply-templates select="*[local-name()=$relationship-names/Vocab:local-name and namespace-uri()=$relationship-names/Vocab:namespace]" mode="Vocab:format-get">
199 <with-param name="source" select="$source"/>
200 </apply-templates>
201 </for-each>
202 <for-each select="key(concat('Vocab:equivalent-', $kind), $source)[@rdf:about]">
203 <apply-templates select="." mode="Vocab:format-get">
204 <with-param name="source" select="string(@rdf:about)"/>
205 </apply-templates>
206 </for-each>
207 </for-each>
208 </if>
209 </for-each>
210 </variable>
211 <variable name="next-nodes" select="exsl:node-set($next)/*"/>
212 <if test="$include-self">
213 <for-each select="$resource-nodes">
214 <if test="not(@rdf:about and ($exclude|$gotten-nodes|preceding-sibling::*)/@rdf:about[string()=string(current()/@rdf:about)])">
215 <apply-templates select="." mode="Vocab:format-get"/>
216 </if>
217 </for-each>
218 </if>
219 <if test="$next-nodes">
220 <call-template name="Vocab:get-fragment-of-equivalents">
221 <with-param name="kind" select="$kind"/>
222 <with-param name="resource-nodes" select="$next-nodes"/>
223 <with-param name="exclude" select="$exclude"/>
224 <with-param name="gotten">
225 <copy-of select="$gotten-nodes"/>
226 <for-each select="$resource-nodes">
227 <if test="not(@rdf:about and ($gotten-nodes|preceding-sibling::*)/@rdf:about[string()=string(current()/@rdf:about)])">
228 <copy-of select="."/>
229 </if>
230 </for-each>
231 </with-param>
232 </call-template>
233 </if>
234 </template>
235 <template name="Vocab:get-fragment-of-transitives">
236 <param name="kind" select="'individual'"/>
237 <param name="relationship"/>
238 <param name="resource-nodes" select="/.."/> <!-- not yet processed, but selected -->
239 <param name="include-self" select="true()"/> <!-- make false on first run to not include provided nodes -->
240 <param name="exclude" select="/.."/> <!-- leave named nodes out of result -->
241 <param name="gotten" select="/.."/> <!-- already processed -->
242 <variable name="root" select="/"/>
243 <variable name="relationship-names" select="Vocab:relationship-names($kind, $relationship)"/>
244 <if test="string($relationship-names/Vocab:local-name)!=''">
245 <variable name="gotten-nodes" select="exsl:node-set($gotten)/*"/>
246 <variable name="equivalent-nodes" select="Vocab:get-equivalents($resource-nodes, $kind, true(), $gotten-nodes)"/> <!-- already deduped -->
247 <variable name="next"> <!-- new selection -->
248 <for-each select="$equivalent-nodes/@rdf:about">
249 <!-- Iterate over each named resource to get, find it, and get the related resources. -->
250 <variable name="source" select="string()"/>
251 <for-each select="$root">
252 <for-each select="key(concat('Vocab:named-', $kind), $source)">
253 <apply-templates select="*[local-name()=$relationship-names/Vocab:local-name and namespace-uri()=$relationship-names/Vocab:namespace]" mode="Vocab:format-get">
254 <with-param name="source" select="$source"/>
255 </apply-templates>
256 </for-each>
257 </for-each>
258 </for-each>
259 </variable>
260 <variable name="next-nodes" select="exsl:node-set($next)/*"/>
261 <if test="$include-self">
262 <for-each select="$equivalent-nodes">
263 <if test="not(@rdf:about and $exclude/@rdf:about[string()=string(current()/@rdf:about)])">
264 <copy-of select="."/>
265 </if>
266 </for-each>
267 </if>
268 <if test="$next-nodes">
269 <call-template name="Vocab:get-fragment-of-transitives">
270 <with-param name="kind" select="$kind"/>
271 <with-param name="relationship" select="$relationship"/>
272 <with-param name="resource-nodes" select="$next-nodes"/>
273 <with-param name="exclude" select="$exclude"/>
274 <with-param name="gotten">
275 <copy-of select="$gotten-nodes"/>
276 <copy-of select="$equivalent-nodes"/>
277 </with-param>
278 </call-template>
279 </if>
280 </if>
281 </template>
282 <template match="*" mode="Vocab:format-get">
283 <param name="source"/>
284 <choose>
285 <when test="Vocabvocab:inferred-from">
286 <copy-of select="."/>
287 </when>
288 <when test="@rdf:about|@rdf:resource">
289 <element name="rdf:Description">
290 <attribute name="rdf:about">
291 <value-of select="@rdf:about|@rdf:resource"/>
292 </attribute>
293 <if test="string($source)!=''">
294 <element name="Vocabvocab:inferred-from">
295 <attribute name="rdf:resource">
296 <value-of select="$source"/>
297 </attribute>
298 </element>
299 </if>
300 </element>
301 </when>
302 <otherwise>
303 <!-- assume this is a property (like `owl:inverseOf´), not an instance (like `owl:ObjectProperty´); in this case, the members are what is desired -->
304 <for-each select="*">
305 <copy>
306 <copy-of select="@*|node()"/>
307 <if test="string($source)!=''">
308 <element name="Vocabvocab:inferred-from">
309 <attribute name="rdf:resource">
310 <value-of select="$source"/>
311 </attribute>
312 </element>
313 </if>
314 </copy>
315 </for-each>
316 </otherwise>
317 </choose>
318 </template>
319 </transform>
This page took 0.365744 seconds and 5 git commands to generate.