1 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * gsf-opendoc-utils.c: Handle the application neutral portions of OpenDocument
5 * Author: Luciano Wolf (luciano.wolf@indt.org.br)
7 * Copyright (C) 2006 Jody Goldberg (jody@gnome.org)
8 * Copyright (C) 2005-2006 INdT - Instituto Nokia de Tecnologia
9 * http://www.indt.org.br
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of version 2.1 of the GNU Lesser General Public
13 * License as published by the Free Software Foundation.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
26 #include <gsf-config.h>
27 #include <gsf/gsf-opendoc-utils.h>
28 #include <gsf/gsf-meta-names.h>
29 #include <gsf/gsf-doc-meta-data.h>
30 #include <gsf/gsf-timestamp.h>
31 #include <gsf/gsf-docprop-vector.h>
35 #define OFFICE "office:"
39 GsfDocPropVector *keywords;
45 G_MODULE_EXPORT char const *
46 get_gsf_odf_version_string (void)
52 get_gsf_odf_version (void)
59 /* Generated based on:
60 * http://www.oasis-open.org/committees/download.php/12572/OpenDocument-v1.0-os.pdf */
61 /* and OpenDocument-v1.1.pdf */
62 GsfXMLInNS gsf_ooo_ns[] = {
63 /* OOo 1.0.x & 1.1.x */
64 GSF_XML_IN_NS (OO_NS_OFFICE, "http://openoffice.org/2000/office"),
65 GSF_XML_IN_NS (OO_NS_STYLE, "http://openoffice.org/2000/style"),
66 GSF_XML_IN_NS (OO_NS_TEXT, "http://openoffice.org/2000/text"),
67 GSF_XML_IN_NS (OO_NS_TABLE, "http://openoffice.org/2000/table"),
68 GSF_XML_IN_NS (OO_NS_DRAW, "http://openoffice.org/2000/drawing"),
69 GSF_XML_IN_NS (OO_NS_NUMBER, "http://openoffice.org/2000/datastyle"),
70 GSF_XML_IN_NS (OO_NS_CHART, "http://openoffice.org/2000/chart"),
71 GSF_XML_IN_NS (OO_NS_DR3D, "http://openoffice.org/2000/dr3d"),
72 GSF_XML_IN_NS (OO_NS_FORM, "http://openoffice.org/2000/form"),
73 GSF_XML_IN_NS (OO_NS_SCRIPT, "http://openoffice.org/2000/script"),
74 GSF_XML_IN_NS (OO_NS_CONFIG, "http://openoffice.org/2001/config"),
75 GSF_XML_IN_NS (OO_NS_MATH, "http://www.w3.org/1998/Math/MathML"), /* also in 2.0 */
76 GSF_XML_IN_NS (OO_NS_FO, "http://www.w3.org/1999/XSL/Format"),
77 GSF_XML_IN_NS (OO_NS_XLINK, "http://www.w3.org/1999/xlink"), /* also in 2.0 */
78 GSF_XML_IN_NS (OO_NS_SVG, "http://www.w3.org/2000/svg"),
80 /* OOo 1.9.x & 2.0.x */
81 GSF_XML_IN_NS (OO_NS_OFFICE, "urn:oasis:names:tc:opendocument:xmlns:office:1.0"),
82 GSF_XML_IN_NS (OO_NS_STYLE, "urn:oasis:names:tc:opendocument:xmlns:style:1.0"),
83 GSF_XML_IN_NS (OO_NS_TEXT, "urn:oasis:names:tc:opendocument:xmlns:text:1.0"),
84 GSF_XML_IN_NS (OO_NS_TABLE, "urn:oasis:names:tc:opendocument:xmlns:table:1.0"),
85 GSF_XML_IN_NS (OO_NS_DRAW, "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0"),
86 GSF_XML_IN_NS (OO_NS_FO, "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0"),
87 GSF_XML_IN_NS (OO_NS_META, "urn:oasis:names:tc:opendocument:xmlns:meta:1.0"),
88 GSF_XML_IN_NS (OO_NS_NUMBER, "urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0"),
89 GSF_XML_IN_NS (OO_NS_SVG, "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0"),
90 GSF_XML_IN_NS (OO_NS_CHART, "urn:oasis:names:tc:opendocument:xmlns:chart:1.0"),
91 GSF_XML_IN_NS (OO_NS_DR3D, "urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0"),
92 GSF_XML_IN_NS (OO_NS_FORM, "urn:oasis:names:tc:opendocument:xmlns:form:1.0"),
93 GSF_XML_IN_NS (OO_NS_SCRIPT, "urn:oasis:names:tc:opendocument:xmlns:script:1.0"),
94 GSF_XML_IN_NS (OO_NS_PRESENT, "urn:oasis:names:tc:opendocument:xmlns:presentation:1.0"),
96 GSF_XML_IN_NS (OO_NS_DC, "http://purl.org/dc/elements/1.1/"),
97 GSF_XML_IN_NS (OO_NS_OOO, "http://openoffice.org/2004/office"),
98 GSF_XML_IN_NS (OO_NS_OOOW, "http://openoffice.org/2004/writer"),
99 GSF_XML_IN_NS (OO_NS_OOOC, "http://openoffice.org/2004/calc"),
100 GSF_XML_IN_NS (OO_NS_DOM, "http://www.w3.org/2001/xml-events"),
101 GSF_XML_IN_NS (OO_NS_XFORMS, "http://www.w3.org/2002/xforms"),
102 GSF_XML_IN_NS (OO_NS_XSD, "http://www.w3.org/2001/XMLSchema"),
103 GSF_XML_IN_NS (OO_NS_XSI, "http://www.w3.org/2001/XMLSchema-instance"),
106 GSF_XML_IN_NS (OO_NS_OF, "urn:oasis:names:tc:opendocument:xmlns:of:1.2"),
107 GSF_XML_IN_NS (OO_NS_FIELD, "urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0"),
108 GSF_XML_IN_NS (OO_NS_FIELD, "urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:field:1.0"),
109 GSF_XML_IN_NS (OO_NS_FORMX, "urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0"),
111 GSF_XML_IN_NS (OO_NS_RPT, "http://openoffice.org/2005/report"),
112 GSF_XML_IN_NS (OO_NS_RDFA, "http://docs.oasis-open.org/opendocument/meta/rdfa#"),
115 GSF_XML_IN_NS (OO_NS_GRDDL, "http://www.w3.org/2003/g/data-view#"),
116 GSF_XML_IN_NS (OO_NS_XHTML, "http://www.w3.org/1999/xhtml"),
117 GSF_XML_IN_NS (OO_NS_TABLE_OOO, "http://openoffice.org/2009/table"),
120 GSF_XML_IN_NS (OO_NS_CHART_OOO, "http://openoffice.org/2010/chart"),
122 /* Other OpenDocument v 1.1 */
123 GSF_XML_IN_NS (OO_NS_CONFIG, "urn:oasis:names:tc:opendocument:xmlns:config:1.0"),
124 GSF_XML_IN_NS (OO_NS_ANIM, "urn:oasis:names:tc:opendocument:xmlns:animation:1.0"),
125 GSF_XML_IN_NS (OO_NS_DATASTYLE, "urn:oasis:names:tc:opendocument:xmlns:data style:1.0"),
126 GSF_XML_IN_NS (OO_NS_MANIFEST, "urn:oasis:names:tc:opendocument:xmlns:manifest:1.0"),
127 GSF_XML_IN_NS (OO_NS_SMIL, "urn:oasis:names:tc:opendocument:xmlns:smil-compatible:1.0"),
131 GSF_XML_IN_NS (OO_LOTUS_NS_PRODTOOLS, "http://www.ibm.com/xmlns/prodtools"),
133 /* CleverAge ODF Add-in for Microsoft Office 3.0.5224.0 (11.0.8302)*/
134 GSF_XML_IN_NS (OO_CLEVERAGE_NS_DC, "http://purl.org/dc/terms/"),
137 GSF_XML_IN_NS (OO_KDE_NS_KOFFICE, "http://www.koffice.org/2005/"),
139 /* Microsoft Excel Formulas in ODF */
140 GSF_XML_IN_NS (OO_MS_NS_MSOXL, "http://schemas.microsoft.com/office/excel/formula"),
142 /* Gnumeric ODF extensions */
143 GSF_XML_IN_NS (OO_GNUM_NS_EXT, "http://www.gnumeric.org/odf-extension/1.0"),
147 G_MODULE_EXPORT GsfXMLInNS *get_gsf_ooo_ns (void)
154 od_get_meta_prop (GsfXMLIn *xin, char const *prop_name, GType g_type)
156 GValue *res = g_new0 (GValue, 1);
157 if (gsf_xml_gvalue_from_str (res, g_type, xin->content->str))
158 gsf_doc_meta_data_insert (((GsfOOMetaIn *)xin->user_state)->md,
159 g_strdup (prop_name), res);
164 /* Avoid duplication */
165 #define OO_PROP(tag, name, type) \
167 od_meta_ ## tag (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob) \
169 od_get_meta_prop (xin, name, type); \
171 OO_PROP(generator, GSF_META_NAME_GENERATOR, G_TYPE_STRING)
172 OO_PROP(title, GSF_META_NAME_TITLE, G_TYPE_STRING)
173 OO_PROP(description, GSF_META_NAME_DESCRIPTION, G_TYPE_STRING)
174 OO_PROP(subject, GSF_META_NAME_SUBJECT, G_TYPE_STRING)
175 OO_PROP(initial_creator, GSF_META_NAME_INITIAL_CREATOR, G_TYPE_STRING)
176 /* OD considers this the last person to modify the doc, rather than
177 * the DC convention of the person primarilly responsible for its creation */
178 OO_PROP(creator, GSF_META_NAME_CREATOR, G_TYPE_STRING)
180 OO_PROP(printed_by, GSF_META_NAME_PRINTED_BY, G_TYPE_STRING)
182 OO_PROP(date_created, GSF_META_NAME_DATE_CREATED, GSF_TIMESTAMP_TYPE)
183 OO_PROP(date_modified, GSF_META_NAME_DATE_MODIFIED, GSF_TIMESTAMP_TYPE)
184 OO_PROP(print_date, GSF_META_NAME_LAST_PRINTED, GSF_TIMESTAMP_TYPE)
186 OO_PROP(language, GSF_META_NAME_LANGUAGE, G_TYPE_STRING)
187 OO_PROP(editing_cycles, GSF_META_NAME_REVISION_COUNT, G_TYPE_UINT)
188 /* FIXME FIXME FIXME should be durations using format 'PnYnMnDTnHnMnS' */
189 OO_PROP(editing_duration, GSF_META_NAME_EDITING_DURATION, G_TYPE_STRING)
191 /* OD allows multiple keywords, accumulate things and make it an array */
193 od_meta_keyword (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
195 GsfOOMetaIn *mi = (GsfOOMetaIn *)xin->user_state;
196 GValue *v = g_new0 (GValue, 1);
198 if (NULL == mi->keywords)
199 mi->keywords = gsf_docprop_vector_new ();
201 g_value_init (v, G_TYPE_STRING);
202 g_value_set_string (v, xin->content->str);
203 gsf_docprop_vector_append (mi->keywords, v);
208 #define CXML2C(s) ((char const *)(s))
211 od_meta_user_defined (GsfXMLIn *xin, xmlChar const **attrs)
213 GsfOOMetaIn *mi = (GsfOOMetaIn *)xin->user_state;
214 mi->typ = G_TYPE_STRING;
217 for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2) {
218 if (!strcmp (CXML2C (attrs[0]), "meta:name"))
219 mi->name = g_strdup (CXML2C (attrs[1]));
220 else if (!strcmp (CXML2C (attrs[0]), "meta:value-type") ||
221 !strcmp (CXML2C (attrs[0]), "meta:type")) {
223 * "meta:type" is a typo on the write
227 if (!strcmp (CXML2C (attrs[1]), "boolean")) {
228 mi->typ = G_TYPE_BOOLEAN;
229 } else if (!strcmp (CXML2C (attrs[1]), "float")) {
230 mi->typ = G_TYPE_DOUBLE;
231 } else if (!strcmp (CXML2C (attrs[1]), "string")) {
232 mi->typ = G_TYPE_STRING;
233 } else if (!strcmp (CXML2C (attrs[1]), "date") ||
234 !strcmp (CXML2C (attrs[1]), "data")) {
236 * "data" is a typo on the write side that was
239 mi->typ = GSF_TIMESTAMP_TYPE;
240 } else if (!strcmp (CXML2C (attrs[1]), "time")) {
241 mi->typ = G_TYPE_STRING;
242 /* We should be able to do better */
248 if (mi->name == NULL) /* This should not happen */
249 mi->name = g_strdup ("");
253 od_meta_user_defined_end (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
255 GsfOOMetaIn *mi = (GsfOOMetaIn *)xin->user_state;
257 if (mi->name != NULL) {
258 GValue *res = g_new0 (GValue, 1);
260 if (t == G_TYPE_NONE) t = G_TYPE_STRING;
261 if (gsf_xml_gvalue_from_str (res, t, xin->content->str)) {
262 gsf_doc_meta_data_insert (mi->md, mi->name, res);
273 /* These need special handling for attributes */
280 static GsfXMLInNode const gsf_opendoc_meta_st_dtd[] = {
281 GSF_XML_IN_NODE (META, META, OO_NS_OFFICE, "meta", FALSE, NULL, NULL),
282 /* OpenDocument TAGS */
283 GSF_XML_IN_NODE (META, META_GENERATOR, OO_NS_META, "generator", TRUE, NULL, &od_meta_generator),
284 GSF_XML_IN_NODE (META, META_TITLE, OO_NS_DC, "title", TRUE, NULL, &od_meta_title),
285 GSF_XML_IN_NODE (META, META_DESCRIPTION, OO_NS_DC, "description", TRUE, NULL, &od_meta_description),
286 GSF_XML_IN_NODE (META, META_SUBJECT, OO_NS_DC, "subject", TRUE, NULL, &od_meta_subject),
287 GSF_XML_IN_NODE (META, META_KEYWORD, OO_NS_META, "keyword", TRUE, NULL, &od_meta_keyword),
288 GSF_XML_IN_NODE (META, META_INITIAL_CREATOR, OO_NS_META, "initial-creator", TRUE, NULL, &od_meta_initial_creator),
289 GSF_XML_IN_NODE (META, META_CREATOR, OO_NS_DC, "creator", TRUE, NULL, &od_meta_creator),
290 GSF_XML_IN_NODE (META, META_PRINTED_BY, OO_NS_META, "printed-by", TRUE, NULL, &od_meta_printed_by),
291 GSF_XML_IN_NODE (META, META_CREATION_DATE, OO_NS_META, "creation-date", TRUE, NULL, &od_meta_date_created),
292 GSF_XML_IN_NODE (META, META_DATE_MOD, OO_NS_DC, "date", TRUE, NULL, &od_meta_date_modified),
293 GSF_XML_IN_NODE (META, META_PRINT_DATE, OO_NS_META, "print-date", TRUE, NULL, &od_meta_print_date),
294 GSF_XML_IN_NODE (META, META_TEMPLATE, OO_NS_META, "template", FALSE, NULL, NULL),
295 GSF_XML_IN_NODE (META, META_AUTO_RELOAD, OO_NS_META, "auto-reload", FALSE, NULL, NULL),
296 GSF_XML_IN_NODE (META, META_HL_BEHAVIOUR, OO_NS_META, "hyperlink-behaviour", FALSE, NULL, NULL),
297 GSF_XML_IN_NODE (META, META_DOCUMENT_STATS, OO_NS_META, "document-statistic", FALSE, NULL, NULL),
298 GSF_XML_IN_NODE (META, META_LANGUAGE, OO_NS_DC, "language", TRUE, NULL, &od_meta_language),
299 GSF_XML_IN_NODE (META, META_EDITING_CYCLES, OO_NS_META, "editing-cycles", TRUE, NULL, &od_meta_editing_cycles),
300 GSF_XML_IN_NODE (META, META_EDITING_DURATION, OO_NS_META, "editing-duration", TRUE, NULL, &od_meta_editing_duration),
301 GSF_XML_IN_NODE (META, META_USER_DEFINED, OO_NS_META, "user-defined", GSF_XML_CONTENT, &od_meta_user_defined, &od_meta_user_defined_end),
307 gsf_opendoc_metadata_subtree_free (G_GNUC_UNUSED GsfXMLIn *xin, gpointer old_state)
309 GsfOOMetaIn *state = old_state;
311 if (state->keywords) {
312 GValue *val = g_new0 (GValue, 1);
313 g_value_init (val, GSF_DOCPROP_VECTOR_TYPE);
314 g_value_set_object (val, state->keywords);
315 gsf_doc_meta_data_insert (state->md,
316 g_strdup (GSF_META_NAME_KEYWORDS), val);
317 g_object_unref (state->keywords);
320 g_object_unref (G_OBJECT (state->md));
324 static GsfXMLInDoc *doc_subtree = NULL;
327 * gsf_opendoc_metadata_subtree :
328 * @doc : #GsfXMLInDoc
329 * @md : #GsfDocMetaData
331 * Extend @xin so that it can parse a subtree in OpenDoc metadata format
334 gsf_opendoc_metadata_subtree (GsfXMLIn *xin, GsfDocMetaData *md)
336 GsfOOMetaIn *state = NULL;
338 g_return_if_fail (md != NULL);
340 if (NULL == doc_subtree)
341 doc_subtree = gsf_xml_in_doc_new (gsf_opendoc_meta_st_dtd, gsf_ooo_ns);
343 state = g_new0 (GsfOOMetaIn, 1);
345 state->typ = G_TYPE_NONE;
346 g_object_ref (G_OBJECT (md));
347 gsf_xml_in_push_state (xin, doc_subtree, state, gsf_opendoc_metadata_subtree_free, NULL);
351 * gsf_opendoc_metadata_subtree_internal :
352 * @doc : #GsfXMLInDoc
354 * Extend @xin so that it can parse a subtree in OpenDoc metadata format
355 * The current user_state must be a GsfOOMetaIn!
358 gsf_opendoc_metadata_subtree_internal (GsfXMLIn *xin, G_GNUC_UNUSED xmlChar const **attrs)
360 if (NULL == doc_subtree)
361 doc_subtree = gsf_xml_in_doc_new (gsf_opendoc_meta_st_dtd, gsf_ooo_ns);
363 gsf_xml_in_push_state (xin, doc_subtree, NULL, NULL, NULL);
366 static GsfXMLInNode const gsf_opendoc_meta_dtd[] = {
367 GSF_XML_IN_NODE_FULL (START, START, -1, NULL, FALSE, FALSE, TRUE, NULL, NULL, 0),
368 GSF_XML_IN_NODE_FULL (START, META, OO_NS_OFFICE, "meta", FALSE, FALSE, TRUE, &gsf_opendoc_metadata_subtree_internal, NULL, 0),
373 * gsf_opendoc_metadata_read :
375 * @md : #GsfDocMetaData
377 * Read an OpenDocument metadata stream from @input and store the properties
378 * into @md. Overwrite any existing properties with the same id.
380 * Returns: a GError if there is a problem.
383 gsf_opendoc_metadata_read (GsfInput *input, GsfDocMetaData *md)
389 state.keywords = NULL;
393 doc = gsf_xml_in_doc_new (gsf_opendoc_meta_dtd, gsf_ooo_ns);
394 gsf_xml_in_doc_parse (doc, input, &state);
395 gsf_xml_in_doc_free (doc);
397 if (state.keywords) {
398 GValue *val = g_new0 (GValue, 1);
399 g_value_init (val, GSF_DOCPROP_VECTOR_TYPE);
400 g_value_set_object (val, state.keywords);
401 gsf_doc_meta_data_insert (md,
402 g_strdup (GSF_META_NAME_KEYWORDS), val);
403 g_object_unref (state.keywords);
411 od_map_prop_name (char const *name)
413 /* shared by all instances and never freed */
414 static GHashTable *od_prop_name_map = NULL;
416 if (NULL == od_prop_name_map)
422 { GSF_META_NAME_GENERATOR, "meta:generator" },
423 { GSF_META_NAME_TITLE, "dc:title" },
424 { GSF_META_NAME_DESCRIPTION, "dc:description" },
425 { GSF_META_NAME_SUBJECT, "dc:subject" },
426 { GSF_META_NAME_INITIAL_CREATOR,"meta:initial-creator" },
427 { GSF_META_NAME_CREATOR, "dc:creator" },
428 { GSF_META_NAME_PRINTED_BY, "meta:printed-by" },
429 { GSF_META_NAME_DATE_CREATED, "meta:creation-date" },
430 { GSF_META_NAME_DATE_MODIFIED, "dc:date" },
431 { GSF_META_NAME_LAST_PRINTED, "meta:print-date" },
432 { GSF_META_NAME_LANGUAGE, "dc:language" },
433 { GSF_META_NAME_REVISION_COUNT, "meta:editing-cycles" },
434 { GSF_META_NAME_EDITING_DURATION, "meta:editing-duration" }
436 int i = G_N_ELEMENTS (map);
438 od_prop_name_map = g_hash_table_new (g_str_hash, g_str_equal);
440 g_hash_table_insert (od_prop_name_map,
441 (gpointer)map[i].gsf_key,
442 (gpointer)map[i].od_key);
445 return g_hash_table_lookup (od_prop_name_map, name);
449 meta:page-count GSF_META_NAME_PAGE_COUNT
450 meta:table-count GSF_META_NAME_TABLE_COUNT:
452 meta:image-count GSF_META_NAME_IMAGE_COUNT:
453 meta:ole-object-count GSF_META_NAME_OBJECT_COUNT:
454 meta:paragraph-count GSF_META_NAME_PARAGRAPH_COUNT:
456 meta:character-count GSF_META_NAME_CHARACTER_COUNT
457 meta:row-count GSF_META_NAME_LINE_COUNT:
461 meta:non-whitespace-character-count
464 GSF_META_NAME_SPREADSHEET_COUNT
466 GSF_META_NAME_TABLE_COUNT:
468 * GSF_META_NAME_IMAGE_COUNT:
470 GSF_META_NAME_CELL_COUNT
472 GSF_META_NAME_OBJECT_COUNT:
475 GSF_META_NAME_SLIDE_COUNT:
477 GSF_META_NAME_IMAGE_COUNT:
479 GSF_META_NAME_OBJECT_COUNT:
483 meta_write_props (char const *prop_name, GsfDocProp *prop, GsfXMLOut *output)
485 char const *mapped_name;
486 GValue const *val = gsf_doc_prop_get_val (prop);
488 /* Handle specially */
489 if (0 == strcmp (prop_name, GSF_META_NAME_KEYWORDS)) {
494 /* OLE2 stores a single string, with no obvious
495 * standard for seperator */
496 if (G_TYPE_STRING == G_VALUE_TYPE (val)) {
497 str = g_value_dup_string (val);
499 gsf_xml_out_start_element (output, "meta:keyword");
500 gsf_xml_out_add_cstr (output, NULL, str);
501 gsf_xml_out_end_element (output);
504 } else if (NULL != (va = gsf_value_get_docprop_varray (val))) {
505 for (i = 0 ; i < va->n_values; i++) {
506 str = g_value_dup_string (g_value_array_get_nth (va, i));
507 gsf_xml_out_start_element (output, "meta:keyword");
508 gsf_xml_out_add_cstr (output, NULL, str);
509 gsf_xml_out_end_element (output);
516 if (NULL == (mapped_name = od_map_prop_name (prop_name))) {
518 char const *type_name = NULL;
520 gsf_xml_out_start_element (output, "meta:user-defined");
521 gsf_xml_out_add_cstr (output, "meta:name", prop_name);
524 gsf_xml_out_end_element (output);
528 t = G_VALUE_TYPE (val);
535 type_name = "string";
538 type_name = "boolean";
550 if (GSF_TIMESTAMP_TYPE == t)
553 if (NULL != type_name)
554 gsf_xml_out_add_cstr (output, "meta:value-type", type_name);
556 gsf_xml_out_start_element (output, mapped_name);
558 gsf_xml_out_add_gvalue (output, NULL, val);
559 gsf_xml_out_end_element (output);
563 gsf_opendoc_metadata_write (GsfXMLOut *output, GsfDocMetaData const *md)
568 gsf_xml_out_start_element (output, OFFICE "document-meta");
569 gsf_xml_out_add_cstr_unchecked (output, "xmlns:office",
570 "urn:oasis:names:tc:opendocument:xmlns:office:1.0");
571 gsf_xml_out_add_cstr_unchecked (output, "xmlns:xlink",
572 "http://www.w3.org/1999/xlink");
573 gsf_xml_out_add_cstr_unchecked (output, "xmlns:dc",
574 "http://purl.org/dc/elements/1.1/");
575 gsf_xml_out_add_cstr_unchecked (output, "xmlns:meta",
576 "urn:oasis:names:tc:opendocument:xmlns:meta:1.0");
577 gsf_xml_out_add_cstr_unchecked (output, "xmlns:ooo",
578 "http://openoffice.org/2004/office");
579 gsf_xml_out_add_cstr_unchecked (output, "office:version",
580 get_gsf_odf_version_string ());
581 gsf_xml_out_start_element (output, OFFICE "meta");
582 gsf_doc_meta_data_foreach (md, (GHFunc) meta_write_props, output);
583 gsf_xml_out_end_element (output); /* </office:meta> */
585 gsf_xml_out_end_element (output); /* </office:document-meta> */