34
35:- module(rdf_parser,
36 [ xml_to_plrdf/3, 37 element_to_plrdf/3, 38 make_rdf_state/3, 39 rdf_modify_state/3, 40 rdf_name_space/1
41 ]). 42:- use_module(rewrite). 43:- use_module(library(sgml)). 44:- use_module(library(lists)). 45:- use_module(library(uri)). 46:- use_module(library(record)). 47
48:- op(500, fx, \?). 49
50term_expansion(F, T) :- rew_term_expansion(F, T).
51goal_expansion(F, T) :- rew_goal_expansion(F, T).
52
53goal_expansion(attrs(Attrs, List), Goal) :-
54 translate_attrs(List, Attrs, Goal).
55
56translate_attrs(Var, Attrs, rewrite(Var, Attrs)) :-
57 var(Var),
58 !.
59translate_attrs([], _, true) :- !.
60translate_attrs([H], Attrs, Goal) :-
61 !,
62 ( var(H)
63 -> Goal = rewrite(H, Attrs)
64 ; H = \?Optional
65 -> Goal = ( member(A, Attrs),
66 OptRewrite
67 -> true
68 ; true
69 ),
70 expand_goal(rewrite(\Optional, A), OptRewrite)
71 ; Goal = ( member(A, Attrs),
72 Rewrite
73 -> true
74 ),
75 expand_goal(rewrite(H, A), Rewrite)
76 ).
77translate_attrs([H|T], Attrs0, (G0, G1)) :-
78 !,
79 ( var(H)
80 -> G0 = rewrite(H, Attrs0),
81 Attrs1 = Attrs0
82 ; H = \?Optional
83 -> G0 = ( select(A, Attrs0, Attrs1),
84 OptRewrite
85 -> true
86 ; Attrs1 = Attrs0
87 ),
88 expand_goal(rewrite(\Optional, A), OptRewrite)
89 ; G0 = ( select(A, Attrs0, Attrs1),
90 Rewrite
91 ),
92 expand_goal(rewrite(H, A), Rewrite)
93 ),
94 translate_attrs(T, Attrs1, G1).
95translate_attrs(Rule, Attrs, Goal) :-
96 expand_goal(rewrite(Rule, Attrs), Goal).
97
98
99:- multifile rdf_name_space/1. 100:- dynamic rdf_name_space/1. 101
106
107
108rdf_name_space('http://www.w3.org/1999/02/22-rdf-syntax-ns#').
109rdf_name_space('http://www.w3.org/TR/REC-rdf-syntax').
110
111
112:- record
113 rdf_state(base_uri='',
114 lang='',
115 ignore_lang=false,
116 convert_typed_literal). 117
118
125
126xml_to_plrdf(Element, RDF, State) :-
127 ( is_list(Element)
128 -> rewrite(\xml_content_objects(RDF, State), Element)
129 ; rewrite(\xml_objects(RDF, State), Element)
130 ).
131
135
136element_to_plrdf(Element, RDF, State) :-
137 rewrite(\nodeElementList(RDF, State), [Element]).
138
139xml_objects(Objects, Options0) ::=
140 E0,
141 { modify_state(E0, Options0, E, Options), !,
142 rewrite(\xml_objects(Objects, Options), E)
143 }.
144xml_objects(Objects, Options) ::=
145 element((\rdf('RDF'), !),
146 _,
147 \nodeElementList(Objects, Options)),
148 !.
149xml_objects(Objects, Options) ::=
150 element(_, _, \xml_content_objects(Objects, Options)).
151
152xml_content_objects([], _) ::=
153 [].
154xml_content_objects([H|T], Options) ::=
155 [ \xml_objects(H, Options)
156 | \xml_content_objects(T, Options)
157 ].
158
159
160nodeElementList([], _Options) ::=
161 [], !.
162nodeElementList(L, Options) ::=
163 [ (\ws, !)
164 | \nodeElementList(L, Options)
165 ].
166nodeElementList([H|T], Options) ::=
167 [ \nodeElementOrError(H, Options)
168 | \nodeElementList(T, Options)
169 ].
170
171nodeElementOrError(H, Options) ::=
172 \nodeElement(H, Options), !.
173nodeElementOrError(unparsed(Data), _Options) ::=
174 Data.
175
176nodeElement(description(Type, About, Properties), Options) ::=
177 \description(Type, About, Properties, Options).
178
179
180 183
184description(Type, About, Properties, Options0) ::=
185 E0,
186 { modify_state(E0, Options0, E, Options), !,
187 rewrite(\description(Type, About, Properties, Options), E)
188 }.
189description(description, About, Properties, Options) ::=
190 element(\rdf('Description'),
191 \attrs([ \?idAboutAttr(About, Options)
192 | \propAttrs(PropAttrs, Options)
193 ]),
194 \propertyElts(PropElts, Options)),
195 { !, append(PropAttrs, PropElts, Properties)
196 }.
197description(Type, About, Properties, Options) ::=
198 element(\name_uri(Type, Options),
199 \attrs([ \?idAboutAttr(About, Options)
200 | \propAttrs(PropAttrs, Options)
201 ]),
202 \propertyElts(PropElts, Options)),
203 { append(PropAttrs, PropElts, Properties)
204 }.
205
206propAttrs([], _) ::=
207 [], !.
208propAttrs([H|T], Options) ::=
209 [ \propAttr(H, Options)
210 | \propAttrs(T, Options)
211 ].
212
213propAttr(rdf:type = URI, Options) ::=
214 \rdf_or_unqualified(type) = \value_uri(URI, Options), !.
215propAttr(Name = Literal, Options) ::=
216 Name = Value,
217 { mkliteral(Value, Literal, Options)
218 }.
219
220propertyElts([], _) ::=
221 [], !.
222propertyElts(Elts, Options) ::=
223 [ (\ws, !)
224 | \propertyElts(Elts, Options)
225 ].
226propertyElts([H|T], Options) ::=
227 [ \propertyElt(H, Options)
228 | \propertyElts(T, Options)
229 ].
230
231propertyElt(E, Options) ::=
232 \propertyElt(Id, Name, Value, Options),
233 { mkprop(Name, Value, Prop),
234 ( var(Id)
235 -> E = Prop
236 ; E = id(Id, Prop)
237 )
238 }.
239
240mkprop(NS:Local, Value, rdf:Local = Value) :-
241 rdf_name_space(NS),
242 !.
243mkprop(Name, Value, Name = Value).
244
245
246propertyElt(Id, Name, Value, Options0) ::=
247 E0,
248 { modify_state(E0, Options0, E, Options), !,
249 rewrite(\propertyElt(Id, Name, Value, Options), E)
250 }.
251propertyElt(Id, Name, Value, Options) ::=
252 \literalPropertyElt(Id, Name, Value, Options), !.
253propertyElt(_, Name, Literal, Options) ::=
254 element(Name,
255 \attrs([ \parseLiteral
256 ]),
257 Content),
258 { !,
259 literal_value(Content, Literal, Options)
260 }.
261propertyElt(Id, Name, collection(Elements), Options) ::=
262 element(Name,
263 \attrs([ \parseCollection,
264 \?idAttr(Id, Options)
265 ]),
266 \nodeElementList(Elements, Options)).
267 268propertyElt(Id, Name, Value, Options) ::=
269 element(Name, A, \all_ws),
270 { !,
271 rewrite(\emptyPropertyElt(Id, Value, Options), A)
272 }.
273
274propertyElt(_, Name, description(description, Id, Properties), Options) ::=
275 element(Name,
276 \attrs([ \parseResource,
277 \?idAboutAttr(Id, Options)
278 ]),
279 \propertyElts(Properties, Options)),
280 !.
281propertyElt(Id, Name, Literal, Options) ::=
282 element(Name,
283 \attrs([ \?idAttr(Id, Options)
284 ]),
285 [ Value ]),
286 { atom(Value), !,
287 mkliteral(Value, Literal, Options)
288 }.
289propertyElt(Id, Name, Value, Options) ::=
290 element(Name,
291 \attrs([ \?idAttr(Id, Options)
292 ]),
293 \an_rdf_object(Value, Options)), !.
294propertyElt(Id, Name, unparsed(Value), Options) ::=
295 element(Name,
296 \attrs([ \?idAttr(Id, Options)
297 ]),
298 Value).
299
300literalPropertyElt(Id, Name, Literal, Options) ::=
301 element(Name,
302 \attrs([ \typeAttr(Type, Options),
303 \?idAttr(Id, Options)
304 ]),
305 Content),
306 { typed_literal(Type, Content, Literal, Options)
307 }.
308
309emptyPropertyElt(Id, Literal, Options) ::=
310 \attrs([ \?idAttr(Id, Options),
311 \?parseLiteral
312 | \noMoreAttrs
313 ]),
314 { !,
315 mkliteral('', Literal, Options)
316 }.
317emptyPropertyElt(Id,
318 description(description, About, Properties),
319 Options) ::=
320 \attrs([ \?idAttr(Id, Options),
321 \?aboutResourceEmptyElt(About, Options),
322 \?parseResource
323 | \propAttrs(Properties, Options)
324 ]), !.
325
326aboutResourceEmptyElt(about(URI), Options) ::=
327 \resourceAttr(URI, Options), !.
328aboutResourceEmptyElt(node(URI), _Options) ::=
329 \nodeIDAttr(URI).
330
339
340literal_value(Value, literal(type(rdf:'XMLLiteral', Value)), _).
341
346
347mkliteral(Text, literal(Val), Options) :-
348 atom(Text),
349 ( rdf_state_lang(Options, Lang),
350 Lang \== ''
351 -> Val = lang(Lang, Text)
352 ; Val = Text
353 ).
354
360
361typed_literal(Type, Content, literal(Object), Options) :-
362 rdf_state_convert_typed_literal(Options, Convert),
363 nonvar(Convert),
364 !,
365 ( catch(call(Convert, Type, Content, Object), E, true)
366 -> ( var(E)
367 -> true
368 ; Object = E
369 )
370 ; Object = error(cannot_convert(Type, Content), _)
371 ).
372typed_literal(Type, [], literal(type(Type, '')), _Options) :- !.
373typed_literal(Type, [Text], literal(type(Type, Text)), _Options) :- !.
374typed_literal(Type, Content, literal(type(Type, Content)), _Options).
375
376
377idAboutAttr(id(Id), Options) ::=
378 \idAttr(Id, Options), !.
379idAboutAttr(about(About), Options) ::=
380 \aboutAttr(About, Options), !.
381idAboutAttr(node(About), _Options) ::=
382 \nodeIDAttr(About), !.
383
390
391an_rdf_object(Object, Options) ::=
392 [ \nodeElement(Object, Options)
393 ], !.
394an_rdf_object(Object, Options) ::=
395 [ (\ws, !)
396 | \an_rdf_object(Object, Options)
397 ].
398an_rdf_object(Object, Options) ::=
399 [ \nodeElement(Object, Options),
400 \ws
401 ], !.
402
403ws ::=
404 A,
405 { atom(A),
406 atom_chars(A, Chars),
407 all_blank(Chars), !
408 }.
409ws ::=
410 pi(_).
411
412all_ws ::=
413 [], !.
414all_ws ::=
415 [\ws | \all_ws].
416
417all_blank([]).
418all_blank([H|T]) :-
419 char_type(H, space), 420 all_blank(T).
421
422
423 426
427idAttr(Id, Options) ::=
428 \rdf_or_unqualified('ID') = \uniqueid(Id, Options).
429
430aboutAttr(About, Options) ::=
431 \rdf_or_unqualified(about) = \value_uri(About, Options).
432
433nodeIDAttr(About) ::=
434 \rdf_or_unqualified(nodeID) = About.
435
436resourceAttr(URI, Options) ::=
437 \rdf_or_unqualified(resource) = \value_uri(URI, Options).
438
439typeAttr(Type, Options) ::=
440 \rdf_or_unqualified(datatype) = \value_uri(Type, Options).
441
442name_uri(URI, Options) ::=
443 NS:Local,
444 { !, atom_concat(NS, Local, A),
445 rewrite(\value_uri(URI, Options), A)
446 }.
447name_uri(URI, Options) ::=
448 \value_uri(URI, Options).
449
450value_uri(URI, Options) ::=
451 A,
452 { rdf_state_base_uri(Options, Base),
453 ( Base \== []
454 -> iri_normalized(A, Base, URI)
455 ; URI = A
456 )
457 }.
458
459uniqueid(Id, Options) ::=
460 A,
461 { unique_xml_name(A, HashID),
462 make_globalid(HashID, Options, Id)
463 }.
464
465unique_xml_name(Name, HashID) :-
466 atom_concat(#, Name, HashID),
467 ( xml_name(Name)
468 -> true
469 ; print_message(warning, rdf(not_a_name(Name)))
470 ).
471
472make_globalid(In, Options, Id) :-
473 rdf_state_base_uri(Options, Base),
474 iri_normalized(In, Base, Id).
475
476parseLiteral ::= \rdf_or_unqualified(parseType) = 'Literal'.
477parseResource ::= \rdf_or_unqualified(parseType) = 'Resource'.
478parseCollection ::= \rdf_or_unqualified(parseType) = 'Collection'.
479
480
481 484
485rdf(Tag) ::=
486 NS:Tag,
487 { rdf_name_space(NS), !
488 }.
489
490rdf_or_unqualified(Tag) ::=
491 Tag.
492rdf_or_unqualified(Tag) ::=
493 NS:Tag,
494 { rdf_name_space(NS), !
495 }.
496
497
498 501
526
531
532noMoreAttrs ::=
533 [], !.
534noMoreAttrs ::=
535 [ xml:_=_
536 | \noMoreAttrs
537 ].
538
549
550modify_state(element(Name, Attrs0, Content), Options0,
551 element(Name, Attrs, Content), Options) :-
552 modify_a_state(Attrs0, Options0, Attrs, Options),
553 Attrs0 \== Attrs.
554
555rdf_modify_state(Attributes, State0, State) :-
556 modify_a_state(Attributes, State0, _, State).
557
558
559modify_a_state([], Options, [], Options).
560modify_a_state([Name=Value|T0], Options0, T, Options) :-
561 modify_a(Name, Value, Options0, Options1),
562 !,
563 modify_a_state(T0, Options1, T, Options).
564modify_a_state([H|T0], Options0, [H|T], Options) :-
565 modify_a_state(T0, Options0, T, Options).
566
567
568modify_a(xml:base, Base1, Options0, Options) :-
569 !,
570 rdf_state_base_uri(Options0, Base0),
571 remove_fragment(Base1, Base2),
572 iri_normalized(Base2, Base0, Base),
573 set_base_uri_of_rdf_state(Base, Options0, Options).
574modify_a(xml:lang, Lang, Options0, Options) :-
575 !,
576 rdf_state_ignore_lang(Options0, false),
577 !,
578 set_lang_of_rdf_state(Lang, Options0, Options).
579modify_a(xmlns, _, Options, Options).
580modify_a(xmlns:_, _, Options, Options).
581modify_a(xml:_, _, Options, Options).
582
583
587
588remove_fragment(URI, Plain) :-
589 sub_atom(URI, B, _, _, #),
590 !,
591 sub_atom(URI, 0, B, _, Plain).
592remove_fragment(URI, URI).
593
594
595 598
599:- multifile
600 emacs_prolog_colours:term_colours/2,
601 emacs_prolog_colours:goal_classification/2. 602
603expand(c(X), _, X) :- !.
604expand(In, Pattern, Colours) :-
605 compound(In),
606 !,
607 In =.. [F|Args],
608 expand_list(Args, PatternArgs, ColourArgs),
609 Pattern =.. [F|PatternArgs],
610 Colours = functor(F) - ColourArgs.
611expand(X, X, classify).
612
613expand_list([], [], []).
614expand_list([H|T], [PH|PT], [CH|CT]) :-
615 expand(H, PH, CH),
616 expand_list(T, PT, CT).
617
618:- discontiguous
619 term_expansion/2. 620
621term_expansion(term_colours(C),
622 emacs_prolog_colours:term_colours(Pattern, Colours)) :-
623 expand(C, Pattern, Colours).
624
625term_colours((c(head(+(1))) ::= c(match), {c(body)})).
626term_colours((c(head(+(1))) ::= c(match))).
627
628emacs_prolog_colours:goal_classification(\_, expanded).
629
630:- dynamic
631 prolog:meta_goal/2. 632:- multifile
633 prolog:meta_goal/2,
634 prolog:called_by/2. 635
636prolog:meta_goal(rewrite(A, _), [A]).
637prolog:meta_goal(\A, [A+1]).
638
639prolog:called_by(attrs(Attrs, _Term), Called) :-
640 findall(G+1, sub_term(\?G, Attrs), Called, Tail),
641 findall(G+1, sub_term(\G, Attrs), Tail)