mirror of
https://github.com/jmcnamara/libxlsxwriter.git
synced 2026-05-15 22:02:06 -06:00
245 lines
6.2 KiB
C
245 lines
6.2 KiB
C
/*****************************************************************************
|
|
* relationships - A library for creating Excel XLSX relationships files.
|
|
*
|
|
* Used in conjunction with the libxlsxwriter library.
|
|
*
|
|
* Copyright 2014-2019, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
|
|
*
|
|
*/
|
|
|
|
#include <string.h>
|
|
#include "xlsxwriter/xmlwriter.h"
|
|
#include "xlsxwriter/relationships.h"
|
|
#include "xlsxwriter/utility.h"
|
|
|
|
/*
|
|
* Forward declarations.
|
|
*/
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Private functions.
|
|
*
|
|
****************************************************************************/
|
|
|
|
/*
|
|
* Create a new relationships object.
|
|
*/
|
|
lxw_relationships *
|
|
lxw_relationships_new(void)
|
|
{
|
|
lxw_relationships *rels = calloc(1, sizeof(lxw_relationships));
|
|
GOTO_LABEL_ON_MEM_ERROR(rels, mem_error);
|
|
|
|
rels->relationships = calloc(1, sizeof(struct lxw_rel_tuples));
|
|
GOTO_LABEL_ON_MEM_ERROR(rels->relationships, mem_error);
|
|
STAILQ_INIT(rels->relationships);
|
|
|
|
return rels;
|
|
|
|
mem_error:
|
|
lxw_free_relationships(rels);
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* Free a relationships object.
|
|
*/
|
|
void
|
|
lxw_free_relationships(lxw_relationships *rels)
|
|
{
|
|
lxw_rel_tuple *relationship;
|
|
|
|
if (!rels)
|
|
return;
|
|
|
|
if (rels->relationships) {
|
|
while (!STAILQ_EMPTY(rels->relationships)) {
|
|
relationship = STAILQ_FIRST(rels->relationships);
|
|
STAILQ_REMOVE_HEAD(rels->relationships, list_pointers);
|
|
free(relationship->type);
|
|
free(relationship->target);
|
|
free(relationship->target_mode);
|
|
free(relationship);
|
|
}
|
|
|
|
free(rels->relationships);
|
|
}
|
|
|
|
free(rels);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* XML functions.
|
|
*
|
|
****************************************************************************/
|
|
|
|
/*
|
|
* Write the XML declaration.
|
|
*/
|
|
STATIC void
|
|
_relationships_xml_declaration(lxw_relationships *self)
|
|
{
|
|
lxw_xml_declaration(self->file);
|
|
}
|
|
|
|
/*
|
|
* Write the <Relationship> element.
|
|
*/
|
|
STATIC void
|
|
_write_relationship(lxw_relationships *self, const char *type,
|
|
const char *target, const char *target_mode)
|
|
{
|
|
struct xml_attribute_list attributes;
|
|
struct xml_attribute *attribute;
|
|
char r_id[LXW_MAX_ATTRIBUTE_LENGTH] = { 0 };
|
|
|
|
self->rel_id++;
|
|
lxw_snprintf(r_id, LXW_ATTR_32, "rId%d", self->rel_id);
|
|
|
|
LXW_INIT_ATTRIBUTES();
|
|
LXW_PUSH_ATTRIBUTES_STR("Id", r_id);
|
|
LXW_PUSH_ATTRIBUTES_STR("Type", type);
|
|
LXW_PUSH_ATTRIBUTES_STR("Target", target);
|
|
|
|
if (target_mode)
|
|
LXW_PUSH_ATTRIBUTES_STR("TargetMode", target_mode);
|
|
|
|
lxw_xml_empty_tag(self->file, "Relationship", &attributes);
|
|
|
|
LXW_FREE_ATTRIBUTES();
|
|
}
|
|
|
|
/*
|
|
* Write the <Relationships> element.
|
|
*/
|
|
STATIC void
|
|
_write_relationships(lxw_relationships *self)
|
|
{
|
|
struct xml_attribute_list attributes;
|
|
struct xml_attribute *attribute;
|
|
lxw_rel_tuple *rel;
|
|
|
|
LXW_INIT_ATTRIBUTES();
|
|
LXW_PUSH_ATTRIBUTES_STR("xmlns", LXW_SCHEMA_PACKAGE);
|
|
|
|
lxw_xml_start_tag(self->file, "Relationships", &attributes);
|
|
|
|
STAILQ_FOREACH(rel, self->relationships, list_pointers) {
|
|
_write_relationship(self, rel->type, rel->target, rel->target_mode);
|
|
}
|
|
|
|
LXW_FREE_ATTRIBUTES();
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* XML file assembly functions.
|
|
*
|
|
****************************************************************************/
|
|
|
|
/*
|
|
* Assemble and write the XML file.
|
|
*/
|
|
void
|
|
lxw_relationships_assemble_xml_file(lxw_relationships *self)
|
|
{
|
|
/* Write the XML declaration. */
|
|
_relationships_xml_declaration(self);
|
|
|
|
_write_relationships(self);
|
|
|
|
/* Close the relationships tag. */
|
|
lxw_xml_end_tag(self->file, "Relationships");
|
|
}
|
|
|
|
/*
|
|
* Add a generic container relationship to XLSX .rels xml files.
|
|
*/
|
|
STATIC void
|
|
_add_relationship(lxw_relationships *self, const char *schema,
|
|
const char *type, const char *target,
|
|
const char *target_mode)
|
|
{
|
|
lxw_rel_tuple *relationship;
|
|
|
|
if (!schema || !type || !target)
|
|
return;
|
|
|
|
relationship = calloc(1, sizeof(lxw_rel_tuple));
|
|
GOTO_LABEL_ON_MEM_ERROR(relationship, mem_error);
|
|
|
|
relationship->type = calloc(1, LXW_MAX_ATTRIBUTE_LENGTH);
|
|
GOTO_LABEL_ON_MEM_ERROR(relationship->type, mem_error);
|
|
|
|
/* Add the schema to the relationship type. */
|
|
lxw_snprintf(relationship->type, LXW_MAX_ATTRIBUTE_LENGTH, "%s%s",
|
|
schema, type);
|
|
|
|
relationship->target = lxw_strdup(target);
|
|
GOTO_LABEL_ON_MEM_ERROR(relationship->target, mem_error);
|
|
|
|
if (target_mode) {
|
|
relationship->target_mode = lxw_strdup(target_mode);
|
|
GOTO_LABEL_ON_MEM_ERROR(relationship->target_mode, mem_error);
|
|
}
|
|
|
|
STAILQ_INSERT_TAIL(self->relationships, relationship, list_pointers);
|
|
|
|
return;
|
|
|
|
mem_error:
|
|
if (relationship) {
|
|
free(relationship->type);
|
|
free(relationship->target);
|
|
free(relationship->target_mode);
|
|
free(relationship);
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Public functions.
|
|
*
|
|
****************************************************************************/
|
|
|
|
/*
|
|
* Add a document relationship to XLSX .rels xml files.
|
|
*/
|
|
void
|
|
lxw_add_document_relationship(lxw_relationships *self, const char *type,
|
|
const char *target)
|
|
{
|
|
_add_relationship(self, LXW_SCHEMA_DOCUMENT, type, target, NULL);
|
|
}
|
|
|
|
/*
|
|
* Add a package relationship to XLSX .rels xml files.
|
|
*/
|
|
void
|
|
lxw_add_package_relationship(lxw_relationships *self, const char *type,
|
|
const char *target)
|
|
{
|
|
_add_relationship(self, LXW_SCHEMA_PACKAGE, type, target, NULL);
|
|
}
|
|
|
|
/*
|
|
* Add a MS schema package relationship to XLSX .rels xml files.
|
|
*/
|
|
void
|
|
lxw_add_ms_package_relationship(lxw_relationships *self, const char *type,
|
|
const char *target)
|
|
{
|
|
_add_relationship(self, LXW_SCHEMA_MS, type, target, NULL);
|
|
}
|
|
|
|
/*
|
|
* Add a worksheet relationship to sheet .rels xml files.
|
|
*/
|
|
void
|
|
lxw_add_worksheet_relationship(lxw_relationships *self, const char *type,
|
|
const char *target, const char *target_mode)
|
|
{
|
|
_add_relationship(self, LXW_SCHEMA_DOCUMENT, type, target, target_mode);
|
|
}
|