1 | ;;+----------------------------------------------------------------------------- |
---|
2 | ;;+ Isidorus |
---|
3 | ;;+ (c) 2008-2009 Marc Kuester, Christoph Ludwig, Lukas Giessmann |
---|
4 | ;;+ |
---|
5 | ;;+ Isidorus is freely distributable under the LGPL license. |
---|
6 | ;;+ You can find a detailed description in trunk/docs/LGPL-LICENSE.txt. |
---|
7 | ;;+----------------------------------------------------------------------------- |
---|
8 | |
---|
9 | (defpackage :rdf-importer |
---|
10 | (:use :cl :cxml :elephant :datamodel :isidorus-threading :datamodel) |
---|
11 | (:import-from :constants |
---|
12 | *rdf-ns* |
---|
13 | *rdfs-ns* |
---|
14 | *xml-ns* |
---|
15 | *xmlns-ns* |
---|
16 | *xml-string* |
---|
17 | *rdf2tm-ns* |
---|
18 | *xtm2.0-ns* |
---|
19 | *type-instance-psi* |
---|
20 | *type-psi* |
---|
21 | *instance-psi* |
---|
22 | *rdf-statement* |
---|
23 | *rdf-object* |
---|
24 | *rdf-subject* |
---|
25 | *rdf-predicate* |
---|
26 | *rdf2tm-object* |
---|
27 | *rdf2tm-subject* |
---|
28 | *supertype-psi* |
---|
29 | *subtype-psi* |
---|
30 | *supertype-subtype-psi* |
---|
31 | *rdf-nil* |
---|
32 | *rdf-first* |
---|
33 | *rdf-rest* |
---|
34 | *rdf2tm-scope-prefix* |
---|
35 | *tm2rdf-topic-type-uri* |
---|
36 | *tm2rdf-name-type-uri* |
---|
37 | *tm2rdf-name-property* |
---|
38 | *tm2rdf-variant-type-uri* |
---|
39 | *tm2rdf-variant-property* |
---|
40 | *tm2rdf-occurrence-type-uri* |
---|
41 | *tm2rdf-occurrence-property* |
---|
42 | *tm2rdf-role-type-uri* |
---|
43 | *tm2rdf-role-property* |
---|
44 | *tm2rdf-association-type-uri* |
---|
45 | *tm2rdf-association-property* |
---|
46 | *tm2rdf-subjectIdentifier-property* |
---|
47 | *tm2rdf-itemIdentity-property* |
---|
48 | *tm2rdf-subjectLocator-property* |
---|
49 | *tm2rdf-ns* |
---|
50 | *tm2rdf-value-property* |
---|
51 | *tm2rdf-scope-property* |
---|
52 | *tm2rdf-nametype-property* |
---|
53 | *tm2rdf-occurrencetype-property* |
---|
54 | *tm2rdf-roletype-property* |
---|
55 | *tm2rdf-player-property* |
---|
56 | *tm2rdf-associationtype-property* |
---|
57 | *rdf2tm-blank-node-prefix* |
---|
58 | *tm2rdf-reifier-property*) |
---|
59 | (:import-from :xml-constants |
---|
60 | *rdf_core_psis.xtm* |
---|
61 | *core_psis.xtm*) |
---|
62 | (:import-from :xml-tools |
---|
63 | get-attribute |
---|
64 | xpath-fn-string |
---|
65 | xpath-child-elems-by-qname |
---|
66 | xpath-single-child-elem-by-qname |
---|
67 | xpath-select-location-path |
---|
68 | xpath-select-single-location-path |
---|
69 | get-ns-attribute |
---|
70 | clear-child-nodes |
---|
71 | has-qname |
---|
72 | absolute-uri-p |
---|
73 | get-node-name |
---|
74 | child-nodes-or-text |
---|
75 | get-xml-lang |
---|
76 | get-xml-base |
---|
77 | absolutize-value |
---|
78 | absolutize-id |
---|
79 | concatenate-uri |
---|
80 | push-string |
---|
81 | node-to-string) |
---|
82 | (:import-from :xml-importer |
---|
83 | get-uuid |
---|
84 | get-store-spec |
---|
85 | with-tm |
---|
86 | from-topic-elem-to-stub) |
---|
87 | (:import-from :isidorus-threading |
---|
88 | with-reader-lock |
---|
89 | with-writer-lock) |
---|
90 | (:import-from :exceptions |
---|
91 | missing-reference-error |
---|
92 | duplicate-identifier-error) |
---|
93 | (:export :setup-rdf-module |
---|
94 | :rdf-importer |
---|
95 | :init-rdf-module |
---|
96 | :*rdf-core-xtm* |
---|
97 | :*document-id*)) |
---|
98 | |
---|
99 | (in-package :rdf-importer) |
---|
100 | |
---|
101 | (defvar *rdf-types* (list "Description" "List" "Alt" "Bag" "Seq" |
---|
102 | "Statement" "Property" "XMLLiteral" "nil")) |
---|
103 | |
---|
104 | (defvar *rdf-properties* (list "type" "first" "rest" "subject" "predicate" |
---|
105 | "object" "li" "first" "rest")) |
---|
106 | |
---|
107 | (defvar *rdfs-types* (list "Resource" "Literal" "Class" "Datatype" |
---|
108 | "Container" "ContainerMembershipProperty")) |
---|
109 | |
---|
110 | (defvar *rdfs-properties* (list "subClassOf" "subPropertyOf" "domain" |
---|
111 | "range" "range" "label" "comment" |
---|
112 | "member" "seeAlso" "isDefinedBy")) |
---|
113 | |
---|
114 | (defvar *rdf-core-xtm* "rdf_core.xtm") |
---|
115 | |
---|
116 | (defvar *_n-map* nil) |
---|
117 | |
---|
118 | (defvar *document-id* "isidorus-rdf-document") |
---|
119 | |
---|
120 | |
---|
121 | (defun _n-p (node) |
---|
122 | "Returns t if the given value is of the form _[0-9]+" |
---|
123 | (let ((node-name (get-node-name node))) |
---|
124 | (when (and node-name |
---|
125 | (> (length node-name) 0) |
---|
126 | (eql (elt node-name 0) #\_)) |
---|
127 | (let ((rest |
---|
128 | (subseq node-name 1 (length node-name)))) |
---|
129 | (declare (string node-name)) |
---|
130 | (handler-case (let ((int |
---|
131 | (parse-integer rest))) |
---|
132 | int) |
---|
133 | (condition () nil)))))) |
---|
134 | |
---|
135 | |
---|
136 | |
---|
137 | (defun find-_n-name-of-property (property) |
---|
138 | "Returns the properties name of the form rdf:_n or nil." |
---|
139 | (let ((owner |
---|
140 | (find-if |
---|
141 | #'(lambda(x) |
---|
142 | (find-if |
---|
143 | #'(lambda(y) |
---|
144 | (eql (getf y :elem) property)) |
---|
145 | (getf x :props))) |
---|
146 | *_n-map*))) |
---|
147 | (let ((elem (find-if #'(lambda(x) |
---|
148 | (eql (getf x :elem) property)) |
---|
149 | (getf owner :props)))) |
---|
150 | (when elem |
---|
151 | (getf elem :name))))) |
---|
152 | |
---|
153 | |
---|
154 | |
---|
155 | (defun find-_n-name (owner-identifier property) |
---|
156 | "Returns a name of the form rdf:_n of the property element |
---|
157 | when it owns the tagname rdf:li and exists in the *_n-map* list. |
---|
158 | Otherwise the return value is nil." |
---|
159 | (let ((owner (find-if #'(lambda(x) |
---|
160 | (string= (getf x :owner) owner-identifier)) |
---|
161 | *_n-map*))) |
---|
162 | (when owner |
---|
163 | (let ((prop (find-if #'(lambda(x) |
---|
164 | (eql (getf x :elem) property)) |
---|
165 | (getf owner :props)))) |
---|
166 | (getf prop :name))))) |
---|
167 | |
---|
168 | |
---|
169 | (defun set-_n-name (owner-identifier property) |
---|
170 | "Sets a new name of the form _n for the passed property element and |
---|
171 | adds it to the list *_n-map*. If the property already exists in the |
---|
172 | *_n-map* list, there won't be created a new entry but returned the |
---|
173 | stored value name." |
---|
174 | (let ((name (find-_n-name owner-identifier property))) |
---|
175 | (if name |
---|
176 | name |
---|
177 | (let ((owner (find-if #'(lambda(x) |
---|
178 | (string= (getf x :owner) owner-identifier)) |
---|
179 | *_n-map*))) |
---|
180 | (if owner |
---|
181 | (let ((new-name |
---|
182 | (concatenate |
---|
183 | 'string *rdf-ns* "_" |
---|
184 | (write-to-string (+ (length (getf owner :props)) 1))))) |
---|
185 | (push (list :elem property |
---|
186 | :name new-name) |
---|
187 | (getf owner :props)) |
---|
188 | new-name) |
---|
189 | (progn |
---|
190 | (push |
---|
191 | (list :owner owner-identifier |
---|
192 | :props (list |
---|
193 | (list :elem property |
---|
194 | :name (concatenate 'string *rdf-ns* "_1")))) |
---|
195 | *_n-map*) |
---|
196 | "_1")))))) |
---|
197 | |
---|
198 | |
---|
199 | (defun get-type-of-node-name (node) |
---|
200 | (let ((map-item (find-_n-name-of-property node))) |
---|
201 | (if map-item |
---|
202 | map-item |
---|
203 | (let ((node-name (get-node-name node)) |
---|
204 | (node-ns (dom:namespace-uri node))) |
---|
205 | (concatenate-uri node-ns node-name))))) |
---|
206 | |
---|
207 | |
---|
208 | (defun parse-node-name (node) |
---|
209 | "Parses the given node's name to the known rdf/rdfs nodes and arcs. |
---|
210 | If the given name es equal to a property an error is thrown otherwise |
---|
211 | there is displayed a warning when the rdf ord rdfs namespace is used." |
---|
212 | (declare (dom:element node)) |
---|
213 | (let ((node-name (get-node-name node)) |
---|
214 | (node-ns (dom:namespace-uri node)) |
---|
215 | (err-pref "From parse-node-name(): ")) |
---|
216 | (when (string= node-ns *rdf-ns*) |
---|
217 | (when (find node-name *rdf-properties* :test #'string=) |
---|
218 | (error "~ardf:~a is a property and not allowed here!" |
---|
219 | err-pref node-name)) |
---|
220 | (when (string= node-name "RDF") |
---|
221 | (error "~ardf:RDF not allowed here!" |
---|
222 | err-pref)) |
---|
223 | (unless (find node-name *rdf-types* :test #'string=) |
---|
224 | (format t "~aWarning: ~a is not a known RDF type!~%" |
---|
225 | err-pref node-name))) |
---|
226 | (when (string= node-ns *rdfs-ns*) |
---|
227 | (when (find node-name *rdfs-properties* :test #'string=) |
---|
228 | (error "~ardfs:~a is a property and not allowed here!" |
---|
229 | err-pref node-name)) |
---|
230 | (unless (find node-name *rdfs-types* :test #'string=) |
---|
231 | (format t "~aWarning: rdfs:~a is not a known rdfs:type!~%" |
---|
232 | err-pref node-name)))) |
---|
233 | t) |
---|
234 | |
---|
235 | |
---|
236 | (defun parse-node(node) |
---|
237 | "Parses a node that represents a rdf-resource." |
---|
238 | (declare (dom:element node)) |
---|
239 | (parse-node-name node) |
---|
240 | (let ((ID (get-ns-attribute node "ID")) |
---|
241 | (nodeID (get-ns-attribute node "nodeID")) |
---|
242 | (about (get-ns-attribute node "about")) |
---|
243 | (err-pref "From parse-node(): ") |
---|
244 | (resource (get-ns-attribute node "resource")) |
---|
245 | (datatype (get-ns-attribute node "datatype")) |
---|
246 | (parseType (get-ns-attribute node "parseType")) |
---|
247 | (class (get-ns-attribute node "Class" :ns-uri *rdfs-ns*)) |
---|
248 | (subClassOf (get-ns-attribute node "subClassOf" :ns-uri *rdfs-ns*))) |
---|
249 | (when (and about nodeID) |
---|
250 | (error "~ardf:about and rdf:nodeID are not allowed in parallel use: (~a) (~a)!" |
---|
251 | err-pref about nodeID)) |
---|
252 | (when (and ID |
---|
253 | (or about nodeID)) |
---|
254 | (error "~awhen rdf:ID is set the attributes rdf:~a is not allowed: ~a!" |
---|
255 | err-pref (if about "about" "nodeID") (or about nodeID))) |
---|
256 | (unless (or ID nodeID about (dom:has-attribute-ns node *rdf2tm-ns* "UUID")) |
---|
257 | (dom:set-attribute-ns node *rdf2tm-ns* "UUID" (get-uuid))) |
---|
258 | (handler-case (let ((content (child-nodes-or-text node :trim t))) |
---|
259 | (when (stringp content) |
---|
260 | (error "text-content not allowed here!"))) |
---|
261 | (condition (err) (error "~a~a" err-pref err))) |
---|
262 | (when (or resource datatype parseType class subClassOf) |
---|
263 | (error "~a~a is not allowed here (~a)!" |
---|
264 | err-pref (cond |
---|
265 | (resource (concatenate 'string "resource(" |
---|
266 | resource ")")) |
---|
267 | (datatype (concatenate 'string "datatype(" |
---|
268 | datatype ")")) |
---|
269 | (parseType (concatenate 'string "parseType(" |
---|
270 | parseType ")")) |
---|
271 | (class (concatenate 'string "Class(" class ")")) |
---|
272 | (subClassOf (concatenate 'string "subClassOf(" |
---|
273 | subClassOf ")"))) |
---|
274 | (dom:node-name node))) |
---|
275 | (dolist (item *rdf-types*) |
---|
276 | (when (get-ns-attribute node item) |
---|
277 | (error "~ardf:~a is a type and not allowed here!" |
---|
278 | err-pref item))) |
---|
279 | (dolist (item *rdfs-types*) |
---|
280 | (when (get-ns-attribute node item :ns-uri *rdfs-ns*) |
---|
281 | (error "~ardfs:~a is a type and not allowed here!" |
---|
282 | err-pref item)))) |
---|
283 | t) |
---|
284 | |
---|
285 | |
---|
286 | (defun get-node-refs (nodes tm-id parent-xml-base) |
---|
287 | "Returns a list of node references that can be used as topic IDs." |
---|
288 | (when (and nodes |
---|
289 | (> (length nodes) 0)) |
---|
290 | (loop for node across nodes |
---|
291 | collect (let ((xml-base (get-xml-base node :old-base parent-xml-base))) |
---|
292 | (parse-node node) |
---|
293 | (let ((ID (when (get-ns-attribute node "ID") |
---|
294 | (absolutize-id (get-ns-attribute node "ID") |
---|
295 | xml-base tm-id))) |
---|
296 | (nodeID (get-ns-attribute node "nodeID")) |
---|
297 | (about (when (get-ns-attribute node "about") |
---|
298 | (absolutize-value |
---|
299 | (get-ns-attribute node "about") |
---|
300 | xml-base tm-id))) |
---|
301 | (UUID (get-ns-attribute node "UUID" :ns-uri *rdf2tm-ns*))) |
---|
302 | (list :topicid (or ID about nodeID UUID) |
---|
303 | :psi (or ID about))))))) |
---|
304 | |
---|
305 | |
---|
306 | (defun parse-property-name (property owner-identifier) |
---|
307 | "Parses the given property's name to the known rdf/rdfs nodes and arcs. |
---|
308 | If the given name es equal to an node an error is thrown otherwise |
---|
309 | there is displayed a warning when the rdf ord rdfs namespace is used." |
---|
310 | (declare (dom:element property)) |
---|
311 | (let ((property-name (get-node-name property)) |
---|
312 | (property-ns (dom:namespace-uri property)) |
---|
313 | (err-pref "From parse-property-name(): ")) |
---|
314 | (when (string= property-ns *rdf-ns*) |
---|
315 | (when (find property-name *rdf-types* :test #'string=) |
---|
316 | (error "~ardf:~a is a node and not allowed here!" |
---|
317 | err-pref property-name)) |
---|
318 | (when (string= property-name "RDF") |
---|
319 | (error "~ardf:RDF not allowed here!" |
---|
320 | err-pref)) |
---|
321 | (unless (or (find property-name *rdf-properties* :test #'string=) |
---|
322 | (_n-p property)) |
---|
323 | (format t "~aWarning: rdf:~a is not a known RDF property!~%" |
---|
324 | err-pref property-name))) |
---|
325 | (when (string= property-ns *rdfs-ns*) |
---|
326 | (when (find property-name *rdfs-types* :test #'string=) |
---|
327 | (error "~ardfs:~a is a type and not allowed here!" |
---|
328 | err-pref property-name)) |
---|
329 | (unless (find property-name *rdfs-properties* :test #'string=) |
---|
330 | (format t "~aWarning: rdfs:~a is not a known rdfs:type!~%" |
---|
331 | err-pref property-name))) |
---|
332 | (when (and (string= property-ns *rdf-ns*) |
---|
333 | (string= property-name "li")) |
---|
334 | (set-_n-name owner-identifier property))) |
---|
335 | t) |
---|
336 | |
---|
337 | |
---|
338 | (defun parse-property (property owner-identifier) |
---|
339 | "Parses a property that represents a rdf-arc." |
---|
340 | (declare (dom:element property)) |
---|
341 | (let ((err-pref "From parse-property(): ") |
---|
342 | (node-name (get-node-name property)) |
---|
343 | (node-ns (dom:namespace-uri property)) |
---|
344 | (nodeID (get-ns-attribute property "nodeID")) |
---|
345 | (resource (get-ns-attribute property "resource")) |
---|
346 | (datatype (get-ns-attribute property "datatype")) |
---|
347 | (type (get-ns-attribute property "type")) |
---|
348 | (parseType (get-ns-attribute property "parseType")) |
---|
349 | (about (get-ns-attribute property "about")) |
---|
350 | (subClassOf (get-ns-attribute property "subClassOf" :ns-uri *rdfs-ns*)) |
---|
351 | (literals (get-literals-of-property property nil)) |
---|
352 | (content (child-nodes-or-text property :trim t))) |
---|
353 | (parse-property-name property owner-identifier) |
---|
354 | (when (and parseType |
---|
355 | (or nodeID resource datatype type literals)) |
---|
356 | (error "~awhen rdf:parseType is set the attributes: ~a => ~a are not allowed!" |
---|
357 | err-pref |
---|
358 | (append (list (cond (nodeID "rdf:nodeID") |
---|
359 | (resource "rdf:resource") |
---|
360 | (datatype "rdf:datatype") |
---|
361 | (type "rdf:type"))) |
---|
362 | (map 'list #'(lambda(x)(getf x :type)) literals)) |
---|
363 | (append (list (or nodeID resource datatype type)) |
---|
364 | (map 'list #'(lambda(x)(getf x :value)) literals)))) |
---|
365 | (when (and parseType |
---|
366 | (not (or (string= parseType "Resource") |
---|
367 | (string= parseType "Literal") |
---|
368 | (string= parseType "Collection")))) |
---|
369 | (error "~aunknown rdf:parseType: ~a" |
---|
370 | err-pref parseType)) |
---|
371 | (when (and parseType |
---|
372 | (or (string= parseType "Resource") |
---|
373 | (string= parseType "Collection"))) |
---|
374 | (unless (dom:has-attribute-ns property *rdf2tm-ns* "UUID") |
---|
375 | (dom:set-attribute-ns property *rdf2tm-ns* "UUID" (get-uuid)))) |
---|
376 | (when (and parseType (string= parseType "Resource") (stringp content)) |
---|
377 | (error "~ardf:parseType is set to 'Resource' expecting xml content: ~a!" |
---|
378 | err-pref content)) |
---|
379 | (when (and parseType |
---|
380 | (string= parseType "Collection") |
---|
381 | (stringp content)) |
---|
382 | (error "~ardf:parseType is set to 'Collection' expecting resource content: ~a" |
---|
383 | err-pref content)) |
---|
384 | (when (and nodeID resource) |
---|
385 | (error "~aondly one of rdf:nodeID and rdf:resource is allowed: (~a) (~a)!" |
---|
386 | err-pref nodeID resource)) |
---|
387 | (when (and (or nodeID resource type literals) |
---|
388 | datatype) |
---|
389 | (error "~aonly one of ~a and rdf:datatype (~a) is allowed!" |
---|
390 | err-pref |
---|
391 | (cond |
---|
392 | (nodeID (concatenate 'string "rdf:nodeID (" nodeID ")")) |
---|
393 | (resource (concatenate 'string "rdf:resource (" resource ")")) |
---|
394 | (type (concatenate 'string "rdf:type (" type ")")) |
---|
395 | (literals literals)) |
---|
396 | datatype)) |
---|
397 | (when (and (or nodeID resource) |
---|
398 | (> (length content) 0)) |
---|
399 | (error "~awhen ~a is set no content is allowed: ~a!" |
---|
400 | err-pref |
---|
401 | (cond |
---|
402 | (nodeID (concatenate 'string "rdf:nodeID (" nodeID ")")) |
---|
403 | (resource (concatenate 'string "rdf:resource (" resource ")"))) |
---|
404 | content)) |
---|
405 | (when (and type |
---|
406 | (stringp content) |
---|
407 | (> (length content) 0)) |
---|
408 | (error "~awhen rdf:type is set no literal content is allowed: ~a!" |
---|
409 | err-pref content)) |
---|
410 | (when (and (or type |
---|
411 | (and (string= node-name "type") |
---|
412 | (string= node-ns *rdf-ns*)) |
---|
413 | (> (length literals) 0)) |
---|
414 | (not (or nodeID resource)) |
---|
415 | (not content)) |
---|
416 | (unless (dom:has-attribute-ns property *rdf2tm-ns* "UUID") |
---|
417 | (dom:set-attribute-ns property *rdf2tm-ns* "UUID" (get-uuid)))) |
---|
418 | (when (or about subClassOf) |
---|
419 | (error "~a~a not allowed here!" |
---|
420 | err-pref |
---|
421 | (if about |
---|
422 | (concatenate 'string "rdf:about (" about ")") |
---|
423 | (concatenate 'string "rdfs:subClassOf (" subClassOf ")")))) |
---|
424 | (when (and (string= node-name "subClassOf") |
---|
425 | (string= node-ns *rdfs-ns*) |
---|
426 | (not (or nodeID resource content))) |
---|
427 | (unless (dom:has-attribute-ns property *rdf2tm-ns* "UUID") |
---|
428 | (dom:set-attribute-ns property *rdf2tm-ns* "UUID" (get-uuid)))) |
---|
429 | (when (and (or (and (string= node-name "type") |
---|
430 | (string= node-ns *rdf-ns*)) |
---|
431 | (and (string= node-name "subClassOf") |
---|
432 | (string= node-ns *rdfs-ns*))) |
---|
433 | (and (> (length content) 0) |
---|
434 | (stringp content))) |
---|
435 | (error "~awhen property is ~a literal content is not allowed: ~a!" |
---|
436 | err-pref (if (string= node-name "type") |
---|
437 | "rdf:type" |
---|
438 | "rdfs:subClassOf") |
---|
439 | content)) |
---|
440 | (dolist (item *rdf-types*) |
---|
441 | (when (get-ns-attribute property item) |
---|
442 | (error "~ardf:~a is a type and not allowed here!" |
---|
443 | err-pref item))) |
---|
444 | (dolist (item *rdfs-types*) |
---|
445 | (when (get-ns-attribute property item :ns-uri *rdfs-ns*) |
---|
446 | (error "~ardfs:~a is a type and not allowed here!" |
---|
447 | err-pref item)))) |
---|
448 | t) |
---|
449 | |
---|
450 | |
---|
451 | (defun parse-properties-of-node (node owner-identifier) |
---|
452 | "Parses all node's properties by calling the parse-propery |
---|
453 | function and sets all rdf:li properties as a tupple to the |
---|
454 | *_n-map* list." |
---|
455 | (let ((child-nodes (child-nodes-or-text node :trim t))) |
---|
456 | (when (get-ns-attribute node "li") |
---|
457 | (dom:map-node-map |
---|
458 | #'(lambda(attr) |
---|
459 | (when (and (string= (get-node-name attr) "li") |
---|
460 | (string= (dom:namespace-uri attr) *rdf-ns*)) |
---|
461 | (set-_n-name owner-identifier attr))) |
---|
462 | (dom:attributes node))) |
---|
463 | (when child-nodes |
---|
464 | (loop for property across child-nodes |
---|
465 | do (parse-property property owner-identifier)))) |
---|
466 | t) |
---|
467 | |
---|
468 | |
---|
469 | (defun get-absolute-attribute (elem tm-id parent-xml-base attr-name |
---|
470 | &key (ns-uri *rdf-ns*)) |
---|
471 | "Returns an absolute 'attribute' or nil." |
---|
472 | (declare (dom:element elem)) |
---|
473 | (declare (string attr-name)) |
---|
474 | (tm-id-p tm-id "get-ID") |
---|
475 | (let ((attr (get-ns-attribute elem attr-name :ns-uri ns-uri)) |
---|
476 | (xml-base (get-xml-base elem :old-base parent-xml-base))) |
---|
477 | (when attr |
---|
478 | (if (and (string= ns-uri *rdf-ns*) |
---|
479 | (string= attr-name "ID")) |
---|
480 | (absolutize-id attr xml-base tm-id) |
---|
481 | (absolutize-value attr xml-base tm-id))))) |
---|
482 | |
---|
483 | |
---|
484 | (defun get-datatype (elem tm-id parent-xml-base) |
---|
485 | "Returns a datatype value. The default is xml:string." |
---|
486 | (let ((datatype |
---|
487 | (get-absolute-attribute elem tm-id parent-xml-base "datatype"))) |
---|
488 | (if datatype |
---|
489 | datatype |
---|
490 | *xml-string*))) |
---|
491 | |
---|
492 | |
---|
493 | (defun tm-id-p (tm-id fun-name) |
---|
494 | "Checks the validity of the passed tm-id." |
---|
495 | (unless (absolute-uri-p tm-id) |
---|
496 | (error "From ~a(): you must provide a stable identifier (PSI-style) for this TM: ~a!" |
---|
497 | fun-name tm-id))) |
---|
498 | |
---|
499 | |
---|
500 | (defun get-types-of-node (elem tm-id &key (parent-xml-base nil)) |
---|
501 | "Returns a plist of all node's types of the form |
---|
502 | (:topicid <string> :psi <string> :ID <string>)." |
---|
503 | (remove-if |
---|
504 | #'null |
---|
505 | (append (unless (string= (get-type-of-node-name elem) |
---|
506 | (concatenate 'string *rdf-ns* |
---|
507 | "Description")) |
---|
508 | (list |
---|
509 | (list :topicid (get-type-of-node-name elem) |
---|
510 | :psi (get-type-of-node-name elem) |
---|
511 | :ID nil))) |
---|
512 | (get-types-of-node-content elem tm-id parent-xml-base)))) |
---|