mirror of
https://github.com/cookiengineer/audacity
synced 2025-07-25 17:08:07 +02:00
1182 lines
35 KiB
C
1182 lines
35 KiB
C
/* -*- Mode: c; c-basic-offset: 2 -*-
|
|
*
|
|
* raptor_xml_writer.c - Raptor XML Writer for SAX2 events API
|
|
*
|
|
* Copyright (C) 2003-2006, David Beckett http://purl.org/net/dajobe/
|
|
* Copyright (C) 2003-2005, University of Bristol, UK http://www.bristol.ac.uk/
|
|
*
|
|
* This package is Free Software and part of Redland http://librdf.org/
|
|
*
|
|
* It is licensed under the following three licenses as alternatives:
|
|
* 1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
|
|
* 2. GNU General Public License (GPL) V2 or any newer version
|
|
* 3. Apache License, V2.0 or any newer version
|
|
*
|
|
* You may not use this file except in compliance with at least one of
|
|
* the above three licenses.
|
|
*
|
|
* See LICENSE.html or LICENSE.txt at the top of this package for the
|
|
* complete terms and further detail along with the license texts for
|
|
* the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
|
|
*
|
|
*
|
|
*/
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <raptor_config.h>
|
|
#endif
|
|
|
|
#ifdef WIN32
|
|
#include <win32_raptor_config.h>
|
|
#endif
|
|
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#include <stdarg.h>
|
|
#ifdef HAVE_ERRNO_H
|
|
#include <errno.h>
|
|
#endif
|
|
#ifdef HAVE_STDLIB_H
|
|
#include <stdlib.h>
|
|
#endif
|
|
|
|
/* Raptor includes */
|
|
#include "raptor.h"
|
|
#include "raptor_internal.h"
|
|
|
|
#ifndef STANDALONE
|
|
|
|
|
|
typedef enum {
|
|
XML_WRITER_AUTO_INDENT = 1,
|
|
XML_WRITER_AUTO_EMPTY = 2
|
|
} raptor_xml_writer_flags;
|
|
|
|
|
|
#define XML_WRITER_AUTO_INDENT(xml_writer) ((xml_writer->flags & XML_WRITER_AUTO_INDENT) != 0)
|
|
#define XML_WRITER_AUTO_EMPTY(xml_writer) ((xml_writer->flags & XML_WRITER_AUTO_EMPTY) != 0)
|
|
|
|
#define XML_WRITER_FLUSH_CLOSE_BRACKET(xml_writer) \
|
|
if ((xml_writer->flags & XML_WRITER_AUTO_EMPTY) && \
|
|
xml_writer->current_element && \
|
|
!(xml_writer->current_element->content_cdata_seen || \
|
|
xml_writer->current_element->content_element_seen)) { \
|
|
raptor_iostream_write_byte(xml_writer->iostr, '>'); \
|
|
}
|
|
|
|
|
|
/* Define this for far too much output */
|
|
#undef RAPTOR_DEBUG_CDATA
|
|
|
|
|
|
struct raptor_xml_writer_s {
|
|
int canonicalize;
|
|
|
|
int depth;
|
|
|
|
int my_nstack;
|
|
raptor_namespace_stack *nstack;
|
|
int nstack_depth;
|
|
|
|
const raptor_uri_handler *uri_handler;
|
|
void *uri_context;
|
|
|
|
raptor_simple_message_handler error_handler;
|
|
void *error_data;
|
|
|
|
raptor_xml_element* current_element;
|
|
|
|
/* outputting to this iostream */
|
|
raptor_iostream *iostr;
|
|
|
|
/* XML Writer flags - bits defined in enum raptor_xml_writer_flags */
|
|
int flags;
|
|
|
|
/* indentation per level if formatting */
|
|
int indent;
|
|
|
|
/* XML 1.0 (10) or XML 1.1 (11) */
|
|
int xml_version;
|
|
|
|
/* Write XML 1.0 or 1.1 declaration (default 1) */
|
|
int xml_declaration;
|
|
|
|
/* Has writing the XML declaration writing been checked? */
|
|
int xml_declaration_checked;
|
|
};
|
|
|
|
|
|
/* 16 spaces */
|
|
#define SPACES_BUFFER_SIZE sizeof(spaces_buffer)
|
|
static const unsigned char spaces_buffer[] = {
|
|
' ', ' ', ' ', ' ',
|
|
' ', ' ', ' ', ' ',
|
|
' ', ' ', ' ', ' ',
|
|
' ', ' ', ' ', ' '
|
|
};
|
|
|
|
|
|
|
|
/* helper functions */
|
|
static int
|
|
raptor_xml_writer_indent(raptor_xml_writer *xml_writer)
|
|
{
|
|
int num_spaces;
|
|
|
|
num_spaces = xml_writer->depth * xml_writer->indent;
|
|
|
|
/* Do not write an extra newline at the start of the document
|
|
* (after the XML declaration or XMP processing instruction has
|
|
* been writtten)
|
|
*/
|
|
if(xml_writer->xml_declaration_checked == 1)
|
|
xml_writer->xml_declaration_checked++;
|
|
else
|
|
raptor_iostream_write_byte(xml_writer->iostr, '\n');
|
|
|
|
while (num_spaces > 0) {
|
|
|
|
int count = (num_spaces > (int)SPACES_BUFFER_SIZE) ? (int)SPACES_BUFFER_SIZE : num_spaces;
|
|
|
|
raptor_iostream_write_counted_string(xml_writer->iostr, spaces_buffer, count);
|
|
|
|
num_spaces -= count;
|
|
}
|
|
|
|
if(xml_writer->current_element)
|
|
xml_writer->current_element->content_cdata_seen=1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
struct nsd {
|
|
const raptor_namespace *nspace;
|
|
unsigned char *declaration;
|
|
size_t length;
|
|
};
|
|
|
|
|
|
/*
|
|
* FIXME: This is duplicate code taken from raptor_sax2.c:
|
|
* struct nsd
|
|
* raptor_xml_writer_nsd_compare (from raptor_nsd_compare)
|
|
*/
|
|
|
|
static int
|
|
raptor_xml_writer_nsd_compare(const void *a, const void *b)
|
|
{
|
|
struct nsd* nsd_a=(struct nsd*)a;
|
|
struct nsd* nsd_b=(struct nsd*)b;
|
|
return strcmp((const char*)nsd_a->declaration, (const char*)nsd_b->declaration);
|
|
}
|
|
|
|
|
|
static int
|
|
raptor_iostream_write_xml_element_start(raptor_iostream* iostr,
|
|
raptor_xml_element *element,
|
|
raptor_namespace_stack *nstack,
|
|
raptor_simple_message_handler error_handler,
|
|
void *error_data,
|
|
int auto_empty,
|
|
int depth,
|
|
int xml_version)
|
|
{
|
|
struct nsd *nspace_declarations=NULL;
|
|
size_t nspace_declarations_count=0;
|
|
unsigned int i;
|
|
|
|
/* max is 1 per element and 1 for each attribute + size of declared */
|
|
if(nstack) {
|
|
int nspace_max_count=element->attribute_count+1;
|
|
if(element->declared_nspaces)
|
|
nspace_max_count += raptor_sequence_size(element->declared_nspaces);
|
|
|
|
nspace_declarations=(struct nsd*)RAPTOR_CALLOC(nsdarray, nspace_max_count, sizeof(struct nsd));
|
|
if(!nspace_declarations)
|
|
return 1;
|
|
}
|
|
|
|
if(element->name->nspace) {
|
|
if(nstack && !raptor_namespaces_namespace_in_scope(nstack, element->name->nspace)) {
|
|
nspace_declarations[0].declaration=
|
|
raptor_namespaces_format(element->name->nspace,
|
|
&nspace_declarations[0].length);
|
|
if(!nspace_declarations[0].declaration)
|
|
goto error;
|
|
nspace_declarations[0].nspace=element->name->nspace;
|
|
nspace_declarations_count++;
|
|
}
|
|
}
|
|
|
|
if (element->attributes) {
|
|
for(i=0; i < element->attribute_count; i++) {
|
|
/* qname */
|
|
if(element->attributes[i]->nspace) {
|
|
if(nstack &&
|
|
!raptor_namespaces_namespace_in_scope(nstack, element->attributes[i]->nspace) && element->attributes[i]->nspace != element->name->nspace) {
|
|
/* not in scope and not same as element (so already going to be declared)*/
|
|
unsigned int j;
|
|
int declare_me=1;
|
|
|
|
/* check it wasn't an earlier declaration too */
|
|
for (j=0; j < nspace_declarations_count; j++)
|
|
if(nspace_declarations[j].nspace == element->attributes[j]->nspace) {
|
|
declare_me=0;
|
|
break;
|
|
}
|
|
|
|
if(declare_me) {
|
|
nspace_declarations[nspace_declarations_count].declaration=
|
|
raptor_namespaces_format(element->attributes[i]->nspace,
|
|
&nspace_declarations[nspace_declarations_count].length);
|
|
if(!nspace_declarations[nspace_declarations_count].declaration)
|
|
goto error;
|
|
nspace_declarations[nspace_declarations_count].nspace=element->attributes[i]->nspace;
|
|
nspace_declarations_count++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(nstack && element->declared_nspaces &&
|
|
raptor_sequence_size(element->declared_nspaces) > 0) {
|
|
for(i=0; i< (unsigned int)raptor_sequence_size(element->declared_nspaces); i++) {
|
|
raptor_namespace* nspace=(raptor_namespace*)raptor_sequence_get_at(element->declared_nspaces, i);
|
|
unsigned int j;
|
|
int declare_me=1;
|
|
|
|
/* check it wasn't an earlier declaration too */
|
|
for (j=0; j < nspace_declarations_count; j++)
|
|
if(nspace_declarations[j].nspace == nspace) {
|
|
declare_me=0;
|
|
break;
|
|
}
|
|
|
|
if(declare_me) {
|
|
nspace_declarations[nspace_declarations_count].declaration=
|
|
raptor_namespaces_format(nspace,
|
|
&nspace_declarations[nspace_declarations_count].length);
|
|
if(!nspace_declarations[nspace_declarations_count].declaration)
|
|
goto error;
|
|
nspace_declarations[nspace_declarations_count].nspace=nspace;
|
|
nspace_declarations_count++;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
raptor_iostream_write_byte(iostr, '<');
|
|
|
|
if(element->name->nspace && element->name->nspace->prefix_length > 0) {
|
|
raptor_iostream_write_counted_string(iostr,
|
|
(const char*)element->name->nspace->prefix,
|
|
element->name->nspace->prefix_length);
|
|
raptor_iostream_write_byte(iostr, ':');
|
|
}
|
|
raptor_iostream_write_counted_string(iostr,
|
|
(const char*)element->name->local_name,
|
|
element->name->local_name_length);
|
|
|
|
/* declare namespaces */
|
|
if(nspace_declarations_count) {
|
|
/* sort them into the canonical order */
|
|
qsort((void*)nspace_declarations,
|
|
nspace_declarations_count, sizeof(struct nsd),
|
|
raptor_xml_writer_nsd_compare);
|
|
/* add them */
|
|
for (i=0; i < nspace_declarations_count; i++) {
|
|
raptor_iostream_write_byte(iostr, ' ');
|
|
raptor_iostream_write_counted_string(iostr,
|
|
(const char*)nspace_declarations[i].declaration,
|
|
nspace_declarations[i].length);
|
|
RAPTOR_FREE(cstring, nspace_declarations[i].declaration);
|
|
nspace_declarations[i].declaration=NULL;
|
|
|
|
if(raptor_namespace_copy(nstack,
|
|
(raptor_namespace*)nspace_declarations[i].nspace,
|
|
depth))
|
|
goto error;
|
|
}
|
|
}
|
|
|
|
|
|
if(element->attributes) {
|
|
for(i=0; i < element->attribute_count; i++) {
|
|
raptor_iostream_write_byte(iostr, ' ');
|
|
|
|
if(element->attributes[i]->nspace &&
|
|
element->attributes[i]->nspace->prefix_length > 0) {
|
|
raptor_iostream_write_counted_string(iostr,
|
|
(char*)element->attributes[i]->nspace->prefix,
|
|
element->attributes[i]->nspace->prefix_length);
|
|
raptor_iostream_write_byte(iostr, ':');
|
|
}
|
|
|
|
raptor_iostream_write_counted_string(iostr,
|
|
(const char*)element->attributes[i]->local_name,
|
|
element->attributes[i]->local_name_length);
|
|
|
|
raptor_iostream_write_counted_string(iostr, "=\"", 2);
|
|
|
|
raptor_iostream_write_xml_any_escaped_string(iostr,
|
|
element->attributes[i]->value,
|
|
element->attributes[i]->value_length,
|
|
'"',
|
|
xml_version,
|
|
error_handler, error_data);
|
|
raptor_iostream_write_byte(iostr, '"');
|
|
}
|
|
}
|
|
|
|
if (!auto_empty)
|
|
raptor_iostream_write_byte(iostr, '>');
|
|
|
|
if(nstack)
|
|
RAPTOR_FREE(stringarray, nspace_declarations);
|
|
|
|
return 0;
|
|
|
|
/* Clean up nspace_declarations on error */
|
|
error:
|
|
|
|
for (i=0; i < nspace_declarations_count; i++) {
|
|
if(nspace_declarations[i].declaration)
|
|
RAPTOR_FREE(cstring, nspace_declarations[i].declaration);
|
|
}
|
|
|
|
if(nspace_declarations)
|
|
RAPTOR_FREE(stringarray, nspace_declarations);
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int
|
|
raptor_iostream_write_xml_element_end(raptor_iostream* iostr,
|
|
raptor_xml_element *element,
|
|
int is_empty)
|
|
{
|
|
if (is_empty)
|
|
raptor_iostream_write_byte(iostr, '/');
|
|
else {
|
|
|
|
raptor_iostream_write_byte(iostr, '<');
|
|
|
|
raptor_iostream_write_byte(iostr, '/');
|
|
|
|
if(element->name->nspace && element->name->nspace->prefix_length > 0) {
|
|
raptor_iostream_write_counted_string(iostr,
|
|
(const char*)element->name->nspace->prefix,
|
|
element->name->nspace->prefix_length);
|
|
raptor_iostream_write_byte(iostr, ':');
|
|
}
|
|
raptor_iostream_write_counted_string(iostr,
|
|
(const char*)element->name->local_name,
|
|
element->name->local_name_length);
|
|
}
|
|
|
|
raptor_iostream_write_byte(iostr, '>');
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
* raptor_new_xml_writer:
|
|
* @nstack: Namespace stack for the writer to start with (or NULL)
|
|
* @uri_handler: URI handler function
|
|
* @uri_context: URI handler context data
|
|
* @iostr: I/O stream to write to
|
|
* @error_handler: error handler function
|
|
* @error_data: error handler data
|
|
* @canonicalize: unused
|
|
*
|
|
* Constructor - Create a new XML Writer writing XML to a raptor_iostream
|
|
*
|
|
* Return value: a new #raptor_xml_writer object or NULL on failure
|
|
**/
|
|
raptor_xml_writer*
|
|
raptor_new_xml_writer(raptor_namespace_stack *nstack,
|
|
const raptor_uri_handler *uri_handler,
|
|
void *uri_context,
|
|
raptor_iostream* iostr,
|
|
raptor_simple_message_handler error_handler,
|
|
void *error_data,
|
|
int canonicalize)
|
|
{
|
|
raptor_xml_writer* xml_writer;
|
|
|
|
xml_writer=(raptor_xml_writer*)RAPTOR_CALLOC(raptor_xml_writer, 1, sizeof(raptor_xml_writer)+1);
|
|
if(!xml_writer)
|
|
return NULL;
|
|
|
|
xml_writer->nstack_depth=0;
|
|
|
|
xml_writer->uri_handler=uri_handler;
|
|
xml_writer->uri_context=uri_context;
|
|
|
|
xml_writer->error_handler=error_handler;
|
|
xml_writer->error_data=error_data;
|
|
|
|
xml_writer->nstack=nstack;
|
|
if(!xml_writer->nstack) {
|
|
xml_writer->nstack=nstack=raptor_new_namespaces(uri_handler, uri_context,
|
|
error_handler, error_data,
|
|
1);
|
|
xml_writer->my_nstack=1;
|
|
}
|
|
|
|
xml_writer->iostr=iostr;
|
|
|
|
xml_writer->flags = 0;
|
|
xml_writer->indent = 2;
|
|
|
|
xml_writer->xml_version = 10;
|
|
|
|
/* Write XML declaration */
|
|
xml_writer->xml_declaration=1;
|
|
|
|
return xml_writer;
|
|
}
|
|
|
|
|
|
/**
|
|
* raptor_free_xml_writer:
|
|
* @xml_writer: XML writer object
|
|
*
|
|
* Destructor - Free XML Writer
|
|
*
|
|
**/
|
|
void
|
|
raptor_free_xml_writer(raptor_xml_writer* xml_writer)
|
|
{
|
|
if(xml_writer->nstack && xml_writer->my_nstack)
|
|
raptor_free_namespaces(xml_writer->nstack);
|
|
|
|
RAPTOR_FREE(raptor_xml_writer, xml_writer);
|
|
}
|
|
|
|
|
|
static void
|
|
raptor_xml_writer_write_xml_declaration(raptor_xml_writer* xml_writer)
|
|
{
|
|
if(!xml_writer->xml_declaration_checked) {
|
|
/* check that it should be written once only */
|
|
xml_writer->xml_declaration_checked=1;
|
|
|
|
if(xml_writer->xml_declaration) {
|
|
raptor_iostream_write_string(xml_writer->iostr,
|
|
(const unsigned char*)"<?xml version=\"");
|
|
raptor_iostream_write_counted_string(xml_writer->iostr,
|
|
(xml_writer->xml_version == 10) ?
|
|
(const unsigned char*)"1.0" :
|
|
(const unsigned char*)"1.1",
|
|
3);
|
|
raptor_iostream_write_string(xml_writer->iostr,
|
|
(const unsigned char*)"\" encoding=\"utf-8\"?>\n");
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
* raptor_xml_writer_empty_element:
|
|
* @xml_writer: XML writer object
|
|
* @element: XML element object
|
|
*
|
|
* Write an empty XML element to the XML writer.
|
|
*
|
|
* Closes any previous empty element if XML writer feature AUTO_EMPTY
|
|
* is enabled.
|
|
**/
|
|
void
|
|
raptor_xml_writer_empty_element(raptor_xml_writer* xml_writer,
|
|
raptor_xml_element *element)
|
|
{
|
|
raptor_xml_writer_write_xml_declaration(xml_writer);
|
|
|
|
XML_WRITER_FLUSH_CLOSE_BRACKET(xml_writer);
|
|
|
|
raptor_iostream_write_xml_element_start(xml_writer->iostr,
|
|
element,
|
|
xml_writer->nstack,
|
|
xml_writer->error_handler,
|
|
xml_writer->error_data,
|
|
1,
|
|
xml_writer->depth,
|
|
xml_writer->xml_version);
|
|
|
|
raptor_iostream_write_xml_element_end(xml_writer->iostr, element, 1);
|
|
|
|
raptor_namespaces_end_for_depth(xml_writer->nstack, xml_writer->depth);
|
|
}
|
|
|
|
|
|
/**
|
|
* raptor_xml_writer_start_element:
|
|
* @xml_writer: XML writer object
|
|
* @element: XML element object
|
|
*
|
|
* Write a start XML element to the XML writer.
|
|
*
|
|
* Closes any previous empty element if XML writer feature AUTO_EMPTY
|
|
* is enabled.
|
|
*
|
|
* Indents the start element if XML writer feature AUTO_INDENT is enabled.
|
|
**/
|
|
void
|
|
raptor_xml_writer_start_element(raptor_xml_writer* xml_writer,
|
|
raptor_xml_element *element)
|
|
{
|
|
raptor_xml_writer_write_xml_declaration(xml_writer);
|
|
|
|
XML_WRITER_FLUSH_CLOSE_BRACKET(xml_writer);
|
|
|
|
if(XML_WRITER_AUTO_INDENT(xml_writer))
|
|
raptor_xml_writer_indent(xml_writer);
|
|
|
|
raptor_iostream_write_xml_element_start(xml_writer->iostr,
|
|
element,
|
|
xml_writer->nstack,
|
|
xml_writer->error_handler,
|
|
xml_writer->error_data,
|
|
XML_WRITER_AUTO_EMPTY(xml_writer),
|
|
xml_writer->depth,
|
|
xml_writer->xml_version);
|
|
|
|
xml_writer->depth++;
|
|
|
|
/* SJS Note: This "if" clause is necessary because raptor_rdfxml.c
|
|
* uses xml_writer for parseType="literal" and passes in elements
|
|
* whose parent field is already set. The first time this function
|
|
* is called, it sets element->parent to 0, causing the warn-07.rdf
|
|
* test to fail. Subsequent calls to this function set
|
|
* element->parent to its existing value.
|
|
*/
|
|
if (xml_writer->current_element)
|
|
element->parent = xml_writer->current_element;
|
|
|
|
xml_writer->current_element=element;
|
|
if(element && element->parent)
|
|
element->parent->content_element_seen=1;
|
|
}
|
|
|
|
|
|
/**
|
|
* raptor_xml_writer_end_element:
|
|
* @xml_writer: XML writer object
|
|
* @element: XML element object
|
|
*
|
|
* Write an end XML element to the XML writer.
|
|
*
|
|
* Indents the end element if XML writer feature AUTO_INDENT is enabled.
|
|
**/
|
|
void
|
|
raptor_xml_writer_end_element(raptor_xml_writer* xml_writer,
|
|
raptor_xml_element* element)
|
|
{
|
|
int is_empty;
|
|
|
|
xml_writer->depth--;
|
|
|
|
if (XML_WRITER_AUTO_INDENT(xml_writer) && element->content_element_seen)
|
|
raptor_xml_writer_indent(xml_writer);
|
|
|
|
is_empty = XML_WRITER_AUTO_EMPTY(xml_writer) ?
|
|
!(element->content_cdata_seen || element->content_element_seen) : 0;
|
|
|
|
raptor_iostream_write_xml_element_end(xml_writer->iostr, element, is_empty);
|
|
|
|
raptor_namespaces_end_for_depth(xml_writer->nstack, xml_writer->depth);
|
|
|
|
if(xml_writer->current_element)
|
|
xml_writer->current_element = xml_writer->current_element->parent;
|
|
}
|
|
|
|
|
|
/**
|
|
* raptor_xml_writer_cdata:
|
|
* @xml_writer: XML writer object
|
|
* @s: string to XML escape and write
|
|
*
|
|
* Write CDATA XML-escaped to the XML writer.
|
|
*
|
|
* Closes any previous empty element if XML writer feature AUTO_EMPTY
|
|
* is enabled.
|
|
*
|
|
**/
|
|
void
|
|
raptor_xml_writer_cdata(raptor_xml_writer* xml_writer,
|
|
const unsigned char *s)
|
|
{
|
|
raptor_xml_writer_write_xml_declaration(xml_writer);
|
|
|
|
XML_WRITER_FLUSH_CLOSE_BRACKET(xml_writer);
|
|
|
|
raptor_iostream_write_xml_any_escaped_string(xml_writer->iostr,
|
|
s, strlen((const char*)s),
|
|
'\0',
|
|
xml_writer->xml_version,
|
|
xml_writer->error_handler,
|
|
xml_writer->error_data);
|
|
|
|
if(xml_writer->current_element)
|
|
xml_writer->current_element->content_cdata_seen=1;
|
|
}
|
|
|
|
|
|
/**
|
|
* raptor_xml_writer_cdata_counted:
|
|
* @xml_writer: XML writer object
|
|
* @s: string to XML escape and write
|
|
* @len: length of string
|
|
*
|
|
* Write counted CDATA XML-escaped to the XML writer.
|
|
*
|
|
* Closes any previous empty element if XML writer feature AUTO_EMPTY
|
|
* is enabled.
|
|
*
|
|
**/
|
|
void
|
|
raptor_xml_writer_cdata_counted(raptor_xml_writer* xml_writer,
|
|
const unsigned char *s, unsigned int len)
|
|
{
|
|
raptor_xml_writer_write_xml_declaration(xml_writer);
|
|
|
|
XML_WRITER_FLUSH_CLOSE_BRACKET(xml_writer);
|
|
|
|
raptor_iostream_write_xml_any_escaped_string(xml_writer->iostr,
|
|
s, len,
|
|
'\0',
|
|
xml_writer->xml_version,
|
|
xml_writer->error_handler,
|
|
xml_writer->error_data);
|
|
|
|
if(xml_writer->current_element)
|
|
xml_writer->current_element->content_cdata_seen=1;
|
|
}
|
|
|
|
|
|
/**
|
|
* raptor_xml_writer_raw:
|
|
* @xml_writer: XML writer object
|
|
* @s: string to write
|
|
*
|
|
* Write a string raw to the XML writer.
|
|
*
|
|
* Closes any previous empty element if XML writer feature AUTO_EMPTY
|
|
* is enabled.
|
|
*
|
|
**/
|
|
void
|
|
raptor_xml_writer_raw(raptor_xml_writer* xml_writer,
|
|
const unsigned char *s)
|
|
{
|
|
raptor_xml_writer_write_xml_declaration(xml_writer);
|
|
|
|
XML_WRITER_FLUSH_CLOSE_BRACKET(xml_writer);
|
|
|
|
raptor_iostream_write_string(xml_writer->iostr, s);
|
|
|
|
if(xml_writer->current_element)
|
|
xml_writer->current_element->content_cdata_seen=1;
|
|
}
|
|
|
|
|
|
/**
|
|
* raptor_xml_writer_raw_counted:
|
|
* @xml_writer: XML writer object
|
|
* @s: string to write
|
|
* @len: length of string
|
|
*
|
|
* Write a counted string raw to the XML writer.
|
|
*
|
|
* Closes any previous empty element if XML writer feature AUTO_EMPTY
|
|
* is enabled.
|
|
*
|
|
**/
|
|
void
|
|
raptor_xml_writer_raw_counted(raptor_xml_writer* xml_writer,
|
|
const unsigned char *s, unsigned int len)
|
|
{
|
|
raptor_xml_writer_write_xml_declaration(xml_writer);
|
|
|
|
XML_WRITER_FLUSH_CLOSE_BRACKET(xml_writer);
|
|
|
|
raptor_iostream_write_counted_string(xml_writer->iostr, s, len);
|
|
|
|
if(xml_writer->current_element)
|
|
xml_writer->current_element->content_cdata_seen=1;
|
|
}
|
|
|
|
|
|
/**
|
|
* raptor_xml_writer_comment:
|
|
* @xml_writer: XML writer object
|
|
* @s: comment string to write
|
|
*
|
|
* Write an XML comment to the XML writer.
|
|
*
|
|
* Closes any previous empty element if XML writer feature AUTO_EMPTY
|
|
* is enabled.
|
|
*
|
|
**/
|
|
void
|
|
raptor_xml_writer_comment(raptor_xml_writer* xml_writer,
|
|
const unsigned char *s)
|
|
{
|
|
XML_WRITER_FLUSH_CLOSE_BRACKET(xml_writer);
|
|
|
|
raptor_xml_writer_raw_counted(xml_writer, (const unsigned char*)"<!-- ", 5);
|
|
raptor_xml_writer_cdata(xml_writer, s);
|
|
raptor_xml_writer_raw_counted(xml_writer, (const unsigned char*)" -->", 4);
|
|
}
|
|
|
|
|
|
/**
|
|
* raptor_xml_writer_comment_counted:
|
|
* @xml_writer: XML writer object
|
|
* @s: comment string to write
|
|
* @len: length of string
|
|
*
|
|
* Write a counted XML comment to the XML writer.
|
|
*
|
|
* Closes any previous empty element if XML writer feature AUTO_EMPTY
|
|
* is enabled.
|
|
*
|
|
**/
|
|
void
|
|
raptor_xml_writer_comment_counted(raptor_xml_writer* xml_writer,
|
|
const unsigned char *s, unsigned int len)
|
|
{
|
|
XML_WRITER_FLUSH_CLOSE_BRACKET(xml_writer);
|
|
|
|
raptor_xml_writer_raw_counted(xml_writer, (const unsigned char*)"<!-- ", 5);
|
|
raptor_xml_writer_cdata_counted(xml_writer, s, len);
|
|
raptor_xml_writer_raw_counted(xml_writer, (const unsigned char*)" -->", 4);
|
|
}
|
|
|
|
|
|
/**
|
|
* raptor_xml_writer_features_enumerate:
|
|
* @feature: feature enumeration (0+)
|
|
* @name: pointer to store feature short name (or NULL)
|
|
* @uri: pointer to store feature URI (or NULL)
|
|
* @label: pointer to feature label (or NULL)
|
|
*
|
|
* Get list of xml_writer features.
|
|
*
|
|
* If uri is not NULL, a pointer to a new raptor_uri is returned
|
|
* that must be freed by the caller with raptor_free_uri().
|
|
*
|
|
* Return value: 0 on success, <0 on failure, >0 if feature is unknown
|
|
**/
|
|
int
|
|
raptor_xml_writer_features_enumerate(const raptor_feature feature,
|
|
const char **name,
|
|
raptor_uri **uri, const char **label)
|
|
{
|
|
return raptor_features_enumerate_common(feature, name, uri, label, 8);
|
|
}
|
|
|
|
|
|
/**
|
|
* raptor_xml_writer_set_feature:
|
|
* @xml_writer: #raptor_xml_writer xml_writer object
|
|
* @feature: feature to set from enumerated #raptor_feature values
|
|
* @value: integer feature value (0 or larger)
|
|
*
|
|
* Set xml_writer features with integer values.
|
|
*
|
|
* The allowed features are available via raptor_features_enumerate().
|
|
*
|
|
* Return value: non 0 on failure or if the feature is unknown
|
|
**/
|
|
int
|
|
raptor_xml_writer_set_feature(raptor_xml_writer *xml_writer,
|
|
raptor_feature feature, int value)
|
|
{
|
|
if(value < 0)
|
|
return -1;
|
|
|
|
switch(feature) {
|
|
case RAPTOR_FEATURE_WRITER_AUTO_INDENT:
|
|
if (value)
|
|
xml_writer->flags |= XML_WRITER_AUTO_INDENT;
|
|
else
|
|
xml_writer->flags &= ~XML_WRITER_AUTO_INDENT;
|
|
break;
|
|
|
|
case RAPTOR_FEATURE_WRITER_AUTO_EMPTY:
|
|
if (value)
|
|
xml_writer->flags |= XML_WRITER_AUTO_EMPTY;
|
|
else
|
|
xml_writer->flags &= ~XML_WRITER_AUTO_EMPTY;
|
|
break;
|
|
|
|
case RAPTOR_FEATURE_WRITER_INDENT_WIDTH:
|
|
xml_writer->indent = value;
|
|
break;
|
|
|
|
case RAPTOR_FEATURE_WRITER_XML_VERSION:
|
|
if(value == 10 || value == 11)
|
|
xml_writer->xml_version = value;
|
|
break;
|
|
|
|
case RAPTOR_FEATURE_WRITER_XML_DECLARATION:
|
|
xml_writer->xml_declaration = value;
|
|
break;
|
|
|
|
/* parser features */
|
|
case RAPTOR_FEATURE_SCANNING:
|
|
case RAPTOR_FEATURE_ASSUME_IS_RDF:
|
|
case RAPTOR_FEATURE_ALLOW_NON_NS_ATTRIBUTES:
|
|
case RAPTOR_FEATURE_ALLOW_OTHER_PARSETYPES:
|
|
case RAPTOR_FEATURE_ALLOW_BAGID:
|
|
case RAPTOR_FEATURE_ALLOW_RDF_TYPE_RDF_LIST:
|
|
case RAPTOR_FEATURE_NORMALIZE_LANGUAGE:
|
|
case RAPTOR_FEATURE_NON_NFC_FATAL:
|
|
case RAPTOR_FEATURE_WARN_OTHER_PARSETYPES:
|
|
case RAPTOR_FEATURE_CHECK_RDF_ID:
|
|
case RAPTOR_FEATURE_HTML_TAG_SOUP:
|
|
case RAPTOR_FEATURE_MICROFORMATS:
|
|
case RAPTOR_FEATURE_HTML_LINK:
|
|
case RAPTOR_FEATURE_WWW_TIMEOUT:
|
|
|
|
/* Shared */
|
|
case RAPTOR_FEATURE_NO_NET:
|
|
|
|
/* XML writer features */
|
|
case RAPTOR_FEATURE_RELATIVE_URIS:
|
|
case RAPTOR_FEATURE_START_URI:
|
|
|
|
/* DOT serializer features */
|
|
case RAPTOR_FEATURE_RESOURCE_BORDER:
|
|
case RAPTOR_FEATURE_LITERAL_BORDER:
|
|
case RAPTOR_FEATURE_BNODE_BORDER:
|
|
case RAPTOR_FEATURE_RESOURCE_FILL:
|
|
case RAPTOR_FEATURE_LITERAL_FILL:
|
|
case RAPTOR_FEATURE_BNODE_FILL:
|
|
|
|
/* JSON serializer features */
|
|
case RAPTOR_FEATURE_JSON_CALLBACK:
|
|
case RAPTOR_FEATURE_JSON_EXTRA_DATA:
|
|
|
|
/* Turtle serializer feature */
|
|
case RAPTOR_FEATURE_WRITE_BASE_URI:
|
|
|
|
/* WWW feature */
|
|
case RAPTOR_FEATURE_WWW_HTTP_CACHE_CONTROL:
|
|
case RAPTOR_FEATURE_WWW_HTTP_USER_AGENT:
|
|
|
|
default:
|
|
return -1;
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/**
|
|
* raptor_xml_writer_set_feature_string:
|
|
* @xml_writer: #raptor_xml_writer xml_writer object
|
|
* @feature: feature to set from enumerated #raptor_feature values
|
|
* @value: feature value
|
|
*
|
|
* Set xml_writer features with string values.
|
|
*
|
|
* The allowed features are available via raptor_xml_writer_features_enumerate().
|
|
* If the feature type is integer, the value is interpreted as an integer.
|
|
*
|
|
* Return value: non 0 on failure or if the feature is unknown
|
|
**/
|
|
int
|
|
raptor_xml_writer_set_feature_string(raptor_xml_writer *xml_writer,
|
|
raptor_feature feature,
|
|
const unsigned char *value)
|
|
{
|
|
int value_is_string=(raptor_feature_value_type(feature) == 1);
|
|
if(!value_is_string)
|
|
return raptor_xml_writer_set_feature(xml_writer, feature,
|
|
atoi((const char*)value));
|
|
else
|
|
return -1;
|
|
}
|
|
|
|
|
|
/**
|
|
* raptor_xml_writer_get_feature:
|
|
* @xml_writer: #raptor_xml_writer serializer object
|
|
* @feature: feature to get value
|
|
*
|
|
* Get various xml_writer features.
|
|
*
|
|
* The allowed features are available via raptor_features_enumerate().
|
|
*
|
|
* Note: no feature value is negative
|
|
*
|
|
* Return value: feature value or < 0 for an illegal feature
|
|
**/
|
|
int
|
|
raptor_xml_writer_get_feature(raptor_xml_writer *xml_writer,
|
|
raptor_feature feature)
|
|
{
|
|
int result= -1;
|
|
|
|
switch(feature) {
|
|
case RAPTOR_FEATURE_WRITER_AUTO_INDENT:
|
|
result=XML_WRITER_AUTO_INDENT(xml_writer);
|
|
break;
|
|
|
|
case RAPTOR_FEATURE_WRITER_AUTO_EMPTY:
|
|
result=XML_WRITER_AUTO_EMPTY(xml_writer);
|
|
break;
|
|
|
|
case RAPTOR_FEATURE_WRITER_INDENT_WIDTH:
|
|
result=xml_writer->indent;
|
|
break;
|
|
|
|
case RAPTOR_FEATURE_WRITER_XML_VERSION:
|
|
result=xml_writer->xml_version;
|
|
break;
|
|
|
|
case RAPTOR_FEATURE_WRITER_XML_DECLARATION:
|
|
result=xml_writer->xml_declaration;
|
|
break;
|
|
|
|
/* parser features */
|
|
case RAPTOR_FEATURE_SCANNING:
|
|
case RAPTOR_FEATURE_ASSUME_IS_RDF:
|
|
case RAPTOR_FEATURE_ALLOW_NON_NS_ATTRIBUTES:
|
|
case RAPTOR_FEATURE_ALLOW_OTHER_PARSETYPES:
|
|
case RAPTOR_FEATURE_ALLOW_BAGID:
|
|
case RAPTOR_FEATURE_ALLOW_RDF_TYPE_RDF_LIST:
|
|
case RAPTOR_FEATURE_NORMALIZE_LANGUAGE:
|
|
case RAPTOR_FEATURE_NON_NFC_FATAL:
|
|
case RAPTOR_FEATURE_WARN_OTHER_PARSETYPES:
|
|
case RAPTOR_FEATURE_CHECK_RDF_ID:
|
|
case RAPTOR_FEATURE_HTML_TAG_SOUP:
|
|
case RAPTOR_FEATURE_MICROFORMATS:
|
|
case RAPTOR_FEATURE_HTML_LINK:
|
|
case RAPTOR_FEATURE_WWW_TIMEOUT:
|
|
|
|
/* Shared */
|
|
case RAPTOR_FEATURE_NO_NET:
|
|
|
|
/* XML writer features */
|
|
case RAPTOR_FEATURE_RELATIVE_URIS:
|
|
case RAPTOR_FEATURE_START_URI:
|
|
|
|
/* DOT serializer features */
|
|
case RAPTOR_FEATURE_RESOURCE_BORDER:
|
|
case RAPTOR_FEATURE_LITERAL_BORDER:
|
|
case RAPTOR_FEATURE_BNODE_BORDER:
|
|
case RAPTOR_FEATURE_RESOURCE_FILL:
|
|
case RAPTOR_FEATURE_LITERAL_FILL:
|
|
case RAPTOR_FEATURE_BNODE_FILL:
|
|
|
|
/* JSON serializer features */
|
|
case RAPTOR_FEATURE_JSON_CALLBACK:
|
|
case RAPTOR_FEATURE_JSON_EXTRA_DATA:
|
|
|
|
/* Turtle serializer feature */
|
|
case RAPTOR_FEATURE_WRITE_BASE_URI:
|
|
|
|
/* WWW feature */
|
|
case RAPTOR_FEATURE_WWW_HTTP_CACHE_CONTROL:
|
|
case RAPTOR_FEATURE_WWW_HTTP_USER_AGENT:
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
/**
|
|
* raptor_xml_writer_get_feature_string:
|
|
* @xml_writer: #raptor_xml_writer serializer object
|
|
* @feature: feature to get value
|
|
*
|
|
* Get xml_writer features with string values.
|
|
*
|
|
* The allowed features are available via raptor_features_enumerate().
|
|
*
|
|
* Return value: feature value or NULL for an illegal feature or no value
|
|
**/
|
|
const unsigned char *
|
|
raptor_xml_writer_get_feature_string(raptor_xml_writer *xml_writer,
|
|
raptor_feature feature)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef STANDALONE
|
|
|
|
/* one more prototype */
|
|
int main(int argc, char *argv[]);
|
|
|
|
|
|
const unsigned char *base_uri_string=(const unsigned char*)"http://example.org/base#";
|
|
|
|
#define OUT_BYTES_COUNT 135
|
|
|
|
int
|
|
main(int argc, char *argv[])
|
|
{
|
|
const char *program=raptor_basename(argv[0]);
|
|
const raptor_uri_handler *uri_handler;
|
|
void *uri_context;
|
|
raptor_iostream *iostr;
|
|
raptor_namespace_stack *nstack;
|
|
raptor_namespace* foo_ns;
|
|
raptor_xml_writer* xml_writer;
|
|
raptor_uri* base_uri;
|
|
raptor_qname* el_name;
|
|
raptor_xml_element *element;
|
|
unsigned long offset;
|
|
raptor_qname **attrs;
|
|
raptor_uri* base_uri_copy=NULL;
|
|
|
|
/* for raptor_new_iostream_to_string */
|
|
void *string=NULL;
|
|
size_t string_len=0;
|
|
|
|
raptor_init();
|
|
|
|
iostr=raptor_new_iostream_to_string(&string, &string_len, NULL);
|
|
if(!iostr) {
|
|
fprintf(stderr, "%s: Failed to create iostream to string\n", program);
|
|
exit(1);
|
|
}
|
|
|
|
raptor_uri_get_handler(&uri_handler, &uri_context);
|
|
|
|
nstack=raptor_new_namespaces(uri_handler, uri_context,
|
|
NULL, NULL, /* errors */
|
|
1);
|
|
|
|
xml_writer=raptor_new_xml_writer(nstack,
|
|
uri_handler, uri_context,
|
|
iostr,
|
|
NULL, NULL, /* errors */
|
|
1);
|
|
if(!xml_writer) {
|
|
fprintf(stderr, "%s: Failed to create xml_writer to iostream\n", program);
|
|
exit(1);
|
|
}
|
|
|
|
base_uri=raptor_new_uri(base_uri_string);
|
|
|
|
foo_ns=raptor_new_namespace(nstack,
|
|
(const unsigned char*)"foo",
|
|
(const unsigned char*)"http://example.org/foo-ns#",
|
|
0);
|
|
|
|
|
|
el_name=raptor_new_qname_from_namespace_local_name(foo_ns,
|
|
(const unsigned char*)"bar",
|
|
NULL);
|
|
base_uri_copy=base_uri ? raptor_uri_copy(base_uri) : NULL;
|
|
element=raptor_new_xml_element(el_name,
|
|
NULL, /* language */
|
|
base_uri_copy);
|
|
|
|
raptor_xml_writer_start_element(xml_writer, element);
|
|
raptor_xml_writer_cdata_counted(xml_writer, (const unsigned char*)"hello\n", 6);
|
|
raptor_xml_writer_comment_counted(xml_writer, (const unsigned char*)"comment", 7);
|
|
raptor_xml_writer_cdata(xml_writer, (const unsigned char*)"\n");
|
|
raptor_xml_writer_end_element(xml_writer, element);
|
|
|
|
raptor_free_xml_element(element);
|
|
|
|
raptor_xml_writer_cdata(xml_writer, (const unsigned char*)"\n");
|
|
|
|
el_name=raptor_new_qname(nstack,
|
|
(const unsigned char*)"blah",
|
|
NULL, /* no attribute value - element */
|
|
NULL, NULL); /* errors */
|
|
base_uri_copy=base_uri ? raptor_uri_copy(base_uri) : NULL;
|
|
element=raptor_new_xml_element(el_name,
|
|
NULL, /* language */
|
|
base_uri_copy);
|
|
|
|
attrs=(raptor_qname **)RAPTOR_CALLOC(qnamearray, 1, sizeof(raptor_qname*));
|
|
attrs[0]=raptor_new_qname(nstack,
|
|
(const unsigned char*)"a",
|
|
(const unsigned char*)"b", /* attribute value */
|
|
NULL, NULL); /* errors */
|
|
raptor_xml_element_set_attributes(element, attrs, 1);
|
|
|
|
raptor_xml_writer_empty_element(xml_writer, element);
|
|
|
|
raptor_xml_writer_cdata(xml_writer, (const unsigned char*)"\n");
|
|
|
|
raptor_free_xml_writer(xml_writer);
|
|
|
|
raptor_free_xml_element(element);
|
|
|
|
raptor_free_namespace(foo_ns);
|
|
|
|
raptor_free_namespaces(nstack);
|
|
|
|
raptor_free_uri(base_uri);
|
|
|
|
|
|
offset=raptor_iostream_tell(iostr);
|
|
|
|
#if RAPTOR_DEBUG > 1
|
|
fprintf(stderr, "%s: Freeing iostream\n", program);
|
|
#endif
|
|
raptor_free_iostream(iostr);
|
|
|
|
if(offset != OUT_BYTES_COUNT) {
|
|
fprintf(stderr, "%s: I/O stream wrote %d bytes, expected %d\n", program,
|
|
(int)offset, (int)OUT_BYTES_COUNT);
|
|
fputs("[[", stderr);
|
|
(void)fwrite(string, 1, string_len, stderr);
|
|
fputs("]]\n", stderr);
|
|
return 1;
|
|
}
|
|
|
|
if(!string) {
|
|
fprintf(stderr, "%s: I/O stream failed to create a string\n", program);
|
|
return 1;
|
|
}
|
|
string_len=strlen((const char*)string);
|
|
if(string_len != offset) {
|
|
fprintf(stderr, "%s: I/O stream created a string length %d, expected %d\n", program, (int)string_len, (int)offset);
|
|
return 1;
|
|
}
|
|
|
|
#if RAPTOR_DEBUG > 1
|
|
fprintf(stderr, "%s: Made XML string of %d bytes\n", program, (int)string_len);
|
|
fputs("[[", stderr);
|
|
(void)fwrite(string, 1, string_len, stderr);
|
|
fputs("]]\n", stderr);
|
|
#endif
|
|
|
|
raptor_free_memory(string);
|
|
|
|
|
|
raptor_finish();
|
|
|
|
/* keep gcc -Wall happy */
|
|
return(0);
|
|
}
|
|
|
|
#endif
|