1 /* -*- Mode: c; c-basic-offset: 2 -*-
2 *
3 * raptor_serialize_rdfxml.c - RDF/XML serializer
4 *
5 * Copyright (C) 2004-2008, David Beckett http://www.dajobe.org/
6 * Copyright (C) 2004-2005, University of Bristol, UK http://www.bristol.ac.uk/
7 *
8 * This package is Free Software and part of Redland http://librdf.org/
9 *
10 * It is licensed under the following three licenses as alternatives:
11 * 1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
12 * 2. GNU General Public License (GPL) V2 or any newer version
13 * 3. Apache License, V2.0 or any newer version
14 *
15 * You may not use this file except in compliance with at least one of
16 * the above three licenses.
17 *
18 * See LICENSE.html or LICENSE.txt at the top of this package for the
19 * complete terms and further detail along with the license texts for
20 * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
21 *
22 */
23
24 #ifdef HAVE_CONFIG_H
25 #include <raptor_config.h>
26 #endif
27
28 #include <stdio.h>
29 #include <string.h>
30 #include <ctype.h>
31 #include <stdarg.h>
32 #ifdef HAVE_ERRNO_H
33 #include <errno.h>
34 #endif
35 #ifdef HAVE_STDLIB_H
36 #include <stdlib.h>
37 #endif
38
39 /* Raptor includes */
40 #include "raptor2.h"
41 #include "raptor_internal.h"
42
43
44 /*
45 * Raptor RDF/XML serializer object
46 */
47 typedef struct {
48 /* Namespace stack */
49 raptor_namespace_stack *nstack;
50
51 /* the xml: namespace - this is destroyed when nstack above is deleted */
52 raptor_namespace *xml_nspace;
53
54 /* the rdf: namespace - this is destroyed when nstack above is deleted */
55 raptor_namespace *rdf_nspace;
56
57 /* the rdf:RDF element */
58 raptor_xml_element* rdf_RDF_element;
59
60 /* where the xml is being written */
61 raptor_xml_writer *xml_writer;
62
63 /* User declared namespaces */
64 raptor_sequence *namespaces;
65
66 /* non zero if rdf:RDF has been written (and thus no new namespaces
67 * can be declared).
68 */
69 int written_header;
70 } raptor_rdfxml_serializer_context;
71
72
73 /* local prototypes */
74
75 static void
76 raptor_rdfxml_serialize_terminate(raptor_serializer* serializer);
77
78 /* create a new serializer */
79 static int
raptor_rdfxml_serialize_init(raptor_serializer * serializer,const char * name)80 raptor_rdfxml_serialize_init(raptor_serializer* serializer, const char *name)
81 {
82 raptor_rdfxml_serializer_context* context = (raptor_rdfxml_serializer_context*)serializer->context;
83
84 context->nstack = raptor_new_namespaces(serializer->world, 1);
85 if(!context->nstack)
86 return 1;
87 context->xml_nspace = raptor_new_namespace(context->nstack,
88 (const unsigned char*)"xml",
89 (const unsigned char*)raptor_xml_namespace_uri,
90 0);
91
92 context->rdf_nspace = raptor_new_namespace(context->nstack,
93 (const unsigned char*)"rdf",
94 (const unsigned char*)raptor_rdf_namespace_uri,
95 0);
96
97 context->namespaces = raptor_new_sequence(NULL, NULL);
98
99 if(!context->xml_nspace || !context->rdf_nspace || !context->namespaces) {
100 raptor_rdfxml_serialize_terminate(serializer);
101 return 1;
102 }
103
104 /* Note: item 0 in the list is rdf:RDF's namespace */
105 if(raptor_sequence_push(context->namespaces, context->rdf_nspace)) {
106 raptor_rdfxml_serialize_terminate(serializer);
107 return 1;
108 }
109
110 return 0;
111 }
112
113
114 /* destroy a serializer */
115 static void
raptor_rdfxml_serialize_terminate(raptor_serializer * serializer)116 raptor_rdfxml_serialize_terminate(raptor_serializer* serializer)
117 {
118 raptor_rdfxml_serializer_context* context = (raptor_rdfxml_serializer_context*)serializer->context;
119
120 if(context->xml_writer) {
121 raptor_free_xml_writer(context->xml_writer);
122 context->xml_writer = NULL;
123 }
124
125 if(context->rdf_RDF_element) {
126 raptor_free_xml_element(context->rdf_RDF_element);
127 context->rdf_RDF_element = NULL;
128 }
129
130 if(context->rdf_nspace) {
131 raptor_free_namespace(context->rdf_nspace);
132 context->rdf_nspace = NULL;
133 }
134
135 if(context->xml_nspace) {
136 raptor_free_namespace(context->xml_nspace);
137 context->xml_nspace = NULL;
138 }
139
140 if(context->namespaces) {
141 int i;
142
143 /* Note: item 0 in the list is rdf:RDF's namespace and freed above */
144 for(i = 1; i< raptor_sequence_size(context->namespaces); i++) {
145 raptor_namespace* ns = (raptor_namespace*)raptor_sequence_get_at(context->namespaces, i);
146 if(ns)
147 raptor_free_namespace(ns);
148 }
149 raptor_free_sequence(context->namespaces);
150 context->namespaces = NULL;
151 }
152
153 if(context->nstack) {
154 raptor_free_namespaces(context->nstack);
155 context->nstack = NULL;
156 }
157 }
158
159
160 #define RDFXML_NAMESPACE_DEPTH 0
161
162 /* add a namespace */
163 static int
raptor_rdfxml_serialize_declare_namespace_from_namespace(raptor_serializer * serializer,raptor_namespace * nspace)164 raptor_rdfxml_serialize_declare_namespace_from_namespace(raptor_serializer* serializer,
165 raptor_namespace *nspace)
166 {
167 raptor_rdfxml_serializer_context* context = (raptor_rdfxml_serializer_context*)serializer->context;
168 int i;
169
170 if(context->written_header)
171 return 1;
172
173 for(i = 0; i< raptor_sequence_size(context->namespaces); i++) {
174 raptor_namespace* ns;
175 ns = (raptor_namespace*)raptor_sequence_get_at(context->namespaces, i);
176
177 /* If prefix is already declared, ignore it */
178 if(!ns->prefix && !nspace->prefix)
179 return 1;
180
181 if(ns->prefix && nspace->prefix &&
182 !strcmp((const char*)ns->prefix, (const char*)nspace->prefix))
183 return 1;
184
185 if(ns->uri && nspace->uri &&
186 raptor_uri_equals(ns->uri, nspace->uri))
187 return 1;
188 }
189
190 nspace = raptor_new_namespace_from_uri(context->nstack,
191 nspace->prefix, nspace->uri,
192 RDFXML_NAMESPACE_DEPTH);
193 if(!nspace)
194 return 1;
195
196 raptor_sequence_push(context->namespaces, nspace);
197 return 0;
198 }
199
200
201 /* add a namespace */
202 static int
raptor_rdfxml_serialize_declare_namespace(raptor_serializer * serializer,raptor_uri * uri,const unsigned char * prefix)203 raptor_rdfxml_serialize_declare_namespace(raptor_serializer* serializer,
204 raptor_uri *uri,
205 const unsigned char *prefix)
206 {
207 raptor_rdfxml_serializer_context* context = (raptor_rdfxml_serializer_context*)serializer->context;
208 raptor_namespace *ns;
209 int rc;
210
211 ns = raptor_new_namespace_from_uri(context->nstack, prefix, uri,
212 RDFXML_NAMESPACE_DEPTH);
213
214 rc = raptor_rdfxml_serialize_declare_namespace_from_namespace(serializer,
215 ns);
216 raptor_free_namespace(ns);
217
218 return rc;
219 }
220
221
222 /* start a serialize */
223 static int
raptor_rdfxml_serialize_start(raptor_serializer * serializer)224 raptor_rdfxml_serialize_start(raptor_serializer* serializer)
225 {
226 raptor_rdfxml_serializer_context* context = (raptor_rdfxml_serializer_context*)serializer->context;
227 raptor_xml_writer* xml_writer;
228 raptor_option option;
229
230 if(context->xml_writer) {
231 raptor_free_xml_writer(context->xml_writer);
232 context->xml_writer = NULL;
233 }
234
235 xml_writer = raptor_new_xml_writer(serializer->world, context->nstack,
236 serializer->iostream);
237 if(!xml_writer)
238 return 1;
239
240 option = RAPTOR_OPTION_WRITER_XML_VERSION;
241 raptor_xml_writer_set_option(xml_writer, option, NULL,
242 RAPTOR_OPTIONS_GET_NUMERIC(serializer, option));
243 option = RAPTOR_OPTION_WRITER_XML_DECLARATION;
244 raptor_xml_writer_set_option(xml_writer, option, NULL,
245 RAPTOR_OPTIONS_GET_NUMERIC(serializer, option));
246
247 context->xml_writer = xml_writer;
248 context->written_header = 0;
249
250 return 0;
251 }
252
253
254 static int
raptor_rdfxml_ensure_writen_header(raptor_serializer * serializer,raptor_rdfxml_serializer_context * context)255 raptor_rdfxml_ensure_writen_header(raptor_serializer* serializer,
256 raptor_rdfxml_serializer_context* context)
257 {
258 raptor_xml_writer* xml_writer;
259 raptor_uri *base_uri;
260 int i;
261 raptor_qname **attrs = NULL;
262 int attrs_count = 0;
263 int rc = 1;
264
265 if(context->written_header)
266 return 0;
267
268 context->written_header = 1;
269
270 xml_writer = context->xml_writer;
271
272 base_uri = serializer->base_uri;
273 if(base_uri)
274 base_uri = raptor_uri_copy(base_uri);
275
276 context->rdf_RDF_element = raptor_new_xml_element_from_namespace_local_name(context->rdf_nspace, (const unsigned char*)"RDF", NULL, base_uri);
277 if(!context->rdf_RDF_element)
278 goto tidy;
279
280 /* NOTE: Starts it item 1 as item 0 is the element's namespace (rdf)
281 * and does not need to be declared
282 */
283 for(i = 1; i< raptor_sequence_size(context->namespaces); i++) {
284 raptor_namespace* ns = (raptor_namespace*)raptor_sequence_get_at(context->namespaces, i);
285 if(raptor_xml_element_declare_namespace(context->rdf_RDF_element, ns))
286 goto tidy;
287 }
288
289 if(base_uri &&
290 RAPTOR_OPTIONS_GET_NUMERIC(serializer, RAPTOR_OPTION_WRITE_BASE_URI)) {
291 const unsigned char* base_uri_string;
292
293 attrs = RAPTOR_CALLOC(raptor_qname **, 1, sizeof(raptor_qname*));
294 if(!attrs)
295 goto tidy;
296
297 base_uri_string = raptor_uri_as_string(base_uri);
298 attrs[attrs_count] = raptor_new_qname_from_namespace_local_name(serializer->world, context->xml_nspace, (const unsigned char*)"base", base_uri_string);
299 if(!attrs[attrs_count]) {
300 RAPTOR_FREE(qnamearray, attrs);
301 goto tidy;
302 }
303 attrs_count++;
304 }
305
306 if(attrs_count)
307 raptor_xml_element_set_attributes(context->rdf_RDF_element, attrs,
308 attrs_count);
309 else
310 raptor_xml_element_set_attributes(context->rdf_RDF_element, NULL, 0);
311
312
313 raptor_xml_writer_start_element(xml_writer, context->rdf_RDF_element);
314 raptor_xml_writer_raw_counted(xml_writer, (const unsigned char*)"\n", 1);
315
316 rc = 0;
317
318 tidy:
319 if(base_uri)
320 raptor_free_uri(base_uri);
321
322 return rc;
323 }
324
325
326 /* serialize a statement */
327 static int
raptor_rdfxml_serialize_statement(raptor_serializer * serializer,raptor_statement * statement)328 raptor_rdfxml_serialize_statement(raptor_serializer* serializer,
329 raptor_statement *statement)
330 {
331 raptor_rdfxml_serializer_context* context = (raptor_rdfxml_serializer_context*)serializer->context;
332 raptor_xml_writer* xml_writer = context->xml_writer;
333 unsigned char* uri_string = NULL; /* predicate URI */
334 unsigned char* name = NULL; /* where to split predicate name */
335 unsigned char* subject_uri_string = NULL;
336 unsigned char* object_uri_string = NULL;
337 const unsigned char* nsprefix = (const unsigned char*)"ns0";
338 int rc = 1;
339 size_t len;
340 raptor_xml_element* rdf_Description_element = NULL;
341 raptor_uri* predicate_ns_uri = NULL;
342 raptor_namespace* predicate_ns = NULL;
343 int free_predicate_ns = 0;
344 raptor_xml_element* predicate_element = NULL;
345 raptor_qname **attrs = NULL;
346 int attrs_count = 0;
347 raptor_uri* base_uri = NULL;
348 raptor_term_type object_type;
349 int allocated = 1;
350 int object_is_parseTypeLiteral = 0;
351
352 if(raptor_rdfxml_ensure_writen_header(serializer, context))
353 return 1;
354
355 if(statement->predicate->type == RAPTOR_TERM_TYPE_URI) {
356 unsigned char *p;
357 size_t uri_len;
358 size_t name_len = 1;
359 unsigned char c;
360
361 /* Do not use raptor_uri_as_counted_string() - we want a modifiable copy */
362 uri_string = raptor_uri_to_counted_string(statement->predicate->value.uri,
363 &uri_len);
364 if(!uri_string)
365 goto oom;
366
367 p= uri_string;
368 name_len = uri_len;
369 /* FIXME: this loop could be made smarter */
370 while(name_len >0) {
371 if(raptor_xml_name_check(p, name_len, 10)) {
372 name = p;
373 break;
374 }
375 p++; name_len--;
376 }
377
378 if(!name || (name == uri_string)) {
379 raptor_log_error_formatted(serializer->world, RAPTOR_LOG_LEVEL_ERROR, NULL,
380 "Cannot split predicate URI %s into an XML qname - skipping statement", uri_string);
381 rc = 0; /* skip but do not return an error */
382 goto tidy;
383 }
384
385 c = *name; *name = '\0';
386 predicate_ns_uri = raptor_new_uri(serializer->world, uri_string);
387 *name = c;
388 if(!predicate_ns_uri)
389 goto oom;
390
391 predicate_ns = raptor_namespaces_find_namespace_by_uri(context->nstack,
392 predicate_ns_uri);
393 if(!predicate_ns) {
394 predicate_ns = raptor_new_namespace_from_uri(context->nstack,
395 nsprefix,
396 predicate_ns_uri, 0);
397 if(!predicate_ns) {
398 raptor_free_uri(predicate_ns_uri);
399 goto oom;
400 }
401 free_predicate_ns = 1;
402 }
403 raptor_free_uri(predicate_ns_uri);
404 } else {
405 raptor_log_error_formatted(serializer->world, RAPTOR_LOG_LEVEL_ERROR, NULL,
406 "Cannot serialize a triple with subject node type %d\n",
407 statement->predicate->type);
408 goto tidy;
409 }
410
411 /* base uri */
412 if(serializer->base_uri)
413 base_uri = raptor_uri_copy(serializer->base_uri);
414
415
416 rdf_Description_element = raptor_new_xml_element_from_namespace_local_name(context->rdf_nspace,
417 (unsigned const char*)"Description",
418 NULL, base_uri);
419 if(!rdf_Description_element)
420 goto oom;
421
422 attrs = RAPTOR_CALLOC(raptor_qname**, 3, sizeof(raptor_qname*));
423 if(!attrs)
424 goto oom;
425 attrs_count = 0;
426
427 /* subject */
428 switch(statement->subject->type) {
429 case RAPTOR_TERM_TYPE_BLANK:
430 attrs[attrs_count] = raptor_new_qname_from_namespace_local_name(serializer->world, context->rdf_nspace, (const unsigned char*)"nodeID",
431 statement->subject->value.blank.string);
432 if(!attrs[attrs_count])
433 goto oom;
434 attrs_count++;
435 break;
436
437 case RAPTOR_TERM_TYPE_URI:
438 allocated = 1;
439 if(RAPTOR_OPTIONS_GET_NUMERIC(serializer, RAPTOR_OPTION_RELATIVE_URIS)) {
440 subject_uri_string = raptor_uri_to_relative_uri_string(serializer->base_uri,
441 statement->subject->value.uri);
442 if(!subject_uri_string)
443 goto oom;
444 } else {
445 subject_uri_string = raptor_uri_as_string(statement->subject->value.uri);
446 allocated = 0;
447 }
448
449 attrs[attrs_count] = raptor_new_qname_from_namespace_local_name(serializer->world, context->rdf_nspace, (const unsigned char*)"about", subject_uri_string);
450 if(!attrs[attrs_count]) {
451 if(allocated)
452 RAPTOR_FREE(char*, subject_uri_string);
453 goto oom;
454 }
455 attrs_count++;
456
457 if(allocated)
458 RAPTOR_FREE(char*, subject_uri_string);
459
460 break;
461
462 case RAPTOR_TERM_TYPE_LITERAL:
463 raptor_log_error(serializer->world, RAPTOR_LOG_LEVEL_ERROR, NULL, "Cannot serialize a triple with a literal subject\n");
464 break;
465
466 case RAPTOR_TERM_TYPE_UNKNOWN:
467 default:
468 raptor_log_error_formatted(serializer->world, RAPTOR_LOG_LEVEL_ERROR, NULL,
469 "Cannot serialize a triple with subject node type %d",
470 statement->subject->type);
471 }
472
473 if(attrs_count) {
474 raptor_xml_element_set_attributes(rdf_Description_element, attrs, attrs_count);
475 attrs = NULL; /* attrs ownership transferred to element */
476 }
477
478 raptor_xml_writer_cdata_counted(xml_writer, (const unsigned char*)" ", 2);
479 raptor_xml_writer_start_element(xml_writer, rdf_Description_element);
480 raptor_xml_writer_cdata_counted(xml_writer, (const unsigned char*)"\n", 1);
481
482
483 /* predicate */
484 predicate_element = raptor_new_xml_element_from_namespace_local_name(predicate_ns, name, NULL, base_uri);
485 if(!predicate_element)
486 goto oom;
487
488 /* object */
489 attrs = RAPTOR_CALLOC(raptor_qname**, 3, sizeof(raptor_qname*));
490 if(!attrs)
491 goto oom;
492 attrs_count = 0;
493
494 object_type = statement->object->type;
495 switch(object_type) {
496 case RAPTOR_TERM_TYPE_LITERAL:
497 object_is_parseTypeLiteral = 0;
498 if(statement->object->value.literal.datatype &&
499 raptor_uri_equals(statement->object->value.literal.datatype,
500 RAPTOR_RDF_XMLLiteral_URI(serializer->world)))
501 object_is_parseTypeLiteral = 1;
502
503 if(statement->object->value.literal.language) {
504 attrs[attrs_count] = raptor_new_qname(context->nstack,
505 (unsigned char*)"xml:lang",
506 statement->object->value.literal.language);
507 if(!attrs[attrs_count])
508 goto oom;
509 attrs_count++;
510 }
511 len = statement->object->value.literal.string_len;
512
513 if(object_is_parseTypeLiteral) {
514 attrs[attrs_count] = raptor_new_qname_from_namespace_local_name(serializer->world, context->rdf_nspace, (const unsigned char*)"parseType", (const unsigned char*)"Literal");
515 if(!attrs[attrs_count])
516 goto oom;
517 attrs_count++;
518
519 raptor_xml_element_set_attributes(predicate_element, attrs, attrs_count);
520 attrs = NULL; /* attrs ownership transferred to element */
521
522 raptor_xml_writer_cdata_counted(xml_writer, (const unsigned char*)" ", 4);
523 raptor_xml_writer_start_element(xml_writer, predicate_element);
524
525 /* Print without escaping XML */
526 if(len)
527 raptor_xml_writer_raw_counted(xml_writer,
528 (const unsigned char*)statement->object->value.literal.string,
529 RAPTOR_BAD_CAST(unsigned int, len));
530 } else {
531 if(statement->object->value.literal.datatype) {
532 attrs[attrs_count] = raptor_new_qname_from_namespace_local_name(serializer->world, context->rdf_nspace, (const unsigned char*)"datatype", raptor_uri_as_string(statement->object->value.literal.datatype));
533 if(!attrs[attrs_count])
534 goto oom;
535 attrs_count++;
536 }
537 raptor_xml_element_set_attributes(predicate_element, attrs, attrs_count);
538 attrs = NULL; /* attrs ownership transferred to element */
539
540 raptor_xml_writer_cdata_counted(xml_writer,
541 (const unsigned char*)" ", 4);
542 raptor_xml_writer_start_element(xml_writer, predicate_element);
543
544 if(len)
545 raptor_xml_writer_cdata_counted(xml_writer,
546 statement->object->value.literal.string,
547 RAPTOR_BAD_CAST(unsigned int, len));
548 }
549
550 raptor_xml_writer_end_element(xml_writer, predicate_element);
551 raptor_free_xml_element(predicate_element);
552 predicate_element = NULL;
553 raptor_xml_writer_cdata_counted(xml_writer, (const unsigned char*)"\n", 1);
554
555 break;
556
557 case RAPTOR_TERM_TYPE_BLANK:
558 attrs[attrs_count] = raptor_new_qname_from_namespace_local_name(serializer->world, context->rdf_nspace, (const unsigned char*)"nodeID", statement->object->value.blank.string);
559 if(!attrs[attrs_count])
560 goto oom;
561 attrs_count++;
562
563 raptor_xml_element_set_attributes(predicate_element, attrs, attrs_count);
564 attrs = NULL; /* attrs ownership transferred to element */
565
566 raptor_xml_writer_cdata_counted(xml_writer,
567 (const unsigned char*)" ", 4);
568 raptor_xml_writer_empty_element(xml_writer, predicate_element);
569 raptor_xml_writer_cdata_counted(xml_writer, (const unsigned char*)"\n", 1);
570 break;
571
572 case RAPTOR_TERM_TYPE_URI:
573 /* must be URI */
574 if(RAPTOR_OPTIONS_GET_NUMERIC(serializer, RAPTOR_OPTION_RELATIVE_URIS)) {
575 object_uri_string = raptor_uri_to_relative_uri_string(serializer->base_uri,
576 statement->object->value.uri);
577 } else {
578 object_uri_string = raptor_uri_to_string(statement->object->value.uri);
579 }
580 if(!object_uri_string)
581 goto oom;
582
583 attrs[attrs_count] = raptor_new_qname_from_namespace_local_name(serializer->world, context->rdf_nspace, (const unsigned char*)"resource", object_uri_string);
584 RAPTOR_FREE(char*, object_uri_string);
585
586 if(!attrs[attrs_count])
587 goto oom;
588
589 attrs_count++;
590 raptor_xml_element_set_attributes(predicate_element, attrs, attrs_count);
591 attrs = NULL; /* attrs ownership transferred to element */
592
593 raptor_xml_writer_cdata_counted(xml_writer,
594 (const unsigned char*)" ", 4);
595 raptor_xml_writer_empty_element(xml_writer, predicate_element);
596 raptor_xml_writer_cdata_counted(xml_writer, (const unsigned char*)"\n", 1);
597 break;
598
599 case RAPTOR_TERM_TYPE_UNKNOWN:
600 default:
601 raptor_log_error_formatted(serializer->world, RAPTOR_LOG_LEVEL_ERROR, NULL,
602 "Cannot serialize a triple with object node type %d",
603 object_type);
604 }
605
606 raptor_xml_writer_cdata_counted(xml_writer,
607 (const unsigned char*)" ", 2);
608
609 rc = 0; /* success */
610 goto tidy;
611
612 oom:
613 raptor_log_error(serializer->world, RAPTOR_LOG_LEVEL_FATAL, NULL,
614 "Out of memory");
615
616 tidy:
617
618 if(attrs)
619 RAPTOR_FREE(qnamearray, attrs);
620
621 if(predicate_element)
622 raptor_free_xml_element(predicate_element);
623
624 if(rdf_Description_element) {
625 raptor_xml_writer_end_element(xml_writer, rdf_Description_element);
626 raptor_xml_writer_cdata_counted(xml_writer, (const unsigned char*)"\n", 1);
627 raptor_free_xml_element(rdf_Description_element);
628 }
629
630 if(base_uri)
631 raptor_free_uri(base_uri);
632
633 if(free_predicate_ns)
634 raptor_free_namespace(predicate_ns);
635
636 if(uri_string)
637 RAPTOR_FREE(char*, uri_string);
638
639 return rc;
640 }
641
642
643 /* end a serialize */
644 static int
raptor_rdfxml_serialize_end(raptor_serializer * serializer)645 raptor_rdfxml_serialize_end(raptor_serializer* serializer)
646 {
647 raptor_rdfxml_serializer_context* context = (raptor_rdfxml_serializer_context*)serializer->context;
648 raptor_xml_writer* xml_writer = context->xml_writer;
649
650 if(xml_writer) {
651 /* Make sure an empty RDF/XML document is written when 0 triples
652 * were seen
653 */
654
655 /* ignore ret value */
656 raptor_rdfxml_ensure_writen_header(serializer, context);
657
658 if(context->rdf_RDF_element) {
659 raptor_xml_writer_end_element(xml_writer, context->rdf_RDF_element);
660 raptor_xml_writer_raw_counted(xml_writer, (const unsigned char*)"\n", 1);
661 }
662
663 raptor_xml_writer_flush(xml_writer);
664 }
665
666 if(context->rdf_RDF_element) {
667 raptor_free_xml_element(context->rdf_RDF_element);
668 context->rdf_RDF_element = NULL;
669 }
670
671 return 0;
672 }
673
674
675 /* finish the serializer factory */
676 static void
raptor_rdfxml_serialize_finish_factory(raptor_serializer_factory * factory)677 raptor_rdfxml_serialize_finish_factory(raptor_serializer_factory* factory)
678 {
679
680 }
681
682 static const char* const rdfxml_names[2] = { "rdfxml", NULL};
683
684 static const char* const rdfxml_uri_strings[3] = {
685 "http://www.w3.org/ns/formats/RDF_XML",
686 "http://www.w3.org/TR/rdf-syntax-grammar",
687 NULL
688 };
689
690 #define RDFXML_TYPES_COUNT 2
691 static const raptor_type_q rdfxml_types[RDFXML_TYPES_COUNT + 1] = {
692 { "application/rdf+xml", 19, 10},
693 { "text/rdf", 8, 6},
694 { NULL, 0, 0}
695 };
696
697 static int
raptor_rdfxml_serializer_register_factory(raptor_serializer_factory * factory)698 raptor_rdfxml_serializer_register_factory(raptor_serializer_factory *factory)
699 {
700 factory->desc.names = rdfxml_names;
701 factory->desc.mime_types = rdfxml_types;
702
703 factory->desc.label = "RDF/XML";
704 factory->desc.uri_strings = rdfxml_uri_strings,
705
706 factory->context_length = sizeof(raptor_rdfxml_serializer_context);
707
708 factory->init = raptor_rdfxml_serialize_init;
709 factory->terminate = raptor_rdfxml_serialize_terminate;
710 factory->declare_namespace = raptor_rdfxml_serialize_declare_namespace;
711 factory->declare_namespace_from_namespace = raptor_rdfxml_serialize_declare_namespace_from_namespace;
712 factory->serialize_start = raptor_rdfxml_serialize_start;
713 factory->serialize_statement = raptor_rdfxml_serialize_statement;
714 factory->serialize_end = raptor_rdfxml_serialize_end;
715 factory->finish_factory = raptor_rdfxml_serialize_finish_factory;
716
717 return 0;
718 }
719
720
721
722 int
raptor_init_serializer_rdfxml(raptor_world * world)723 raptor_init_serializer_rdfxml(raptor_world* world)
724 {
725 return !raptor_serializer_register_factory(world,
726 &raptor_rdfxml_serializer_register_factory);
727 }
728
729
730