summaryrefslogtreecommitdiffstats
path: root/librdfa/triple.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:40:05 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:40:05 +0000
commit4038ab95a094b363f1748f3dcb51511a1217475d (patch)
tree7f393d66a783f91ddd263c78d681e485cf4f45ca /librdfa/triple.c
parentInitial commit. (diff)
downloadraptor2-upstream.tar.xz
raptor2-upstream.zip
Adding upstream version 2.0.16.upstream/2.0.16upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'librdfa/triple.c')
-rw-r--r--librdfa/triple.c847
1 files changed, 847 insertions, 0 deletions
diff --git a/librdfa/triple.c b/librdfa/triple.c
new file mode 100644
index 0000000..be1caf2
--- /dev/null
+++ b/librdfa/triple.c
@@ -0,0 +1,847 @@
+/**
+ * Copyright 2008 Digital Bazaar, Inc.
+ *
+ * This file is part of librdfa.
+ *
+ * librdfa is Free Software, and can be licensed under any of the
+ * following three licenses:
+ *
+ * 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-* at the top of this software distribution for more
+ * information regarding the details of each license.
+ *
+ * Handles all triple functionality including all incomplete triple
+ * functionality.
+ *
+ * @author Manu Sporny
+ */
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include "rdfa_utils.h"
+#include "rdfa.h"
+
+rdftriple* rdfa_create_triple(const char* subject, const char* predicate,
+ const char* object, rdfresource_t object_type, const char* datatype,
+ const char* language)
+{
+ rdftriple* rval = (rdftriple*)malloc(sizeof(rdftriple));
+
+ /* clear the memory */
+ rval->subject = NULL;
+ rval->predicate = NULL;
+ rval->object = NULL;
+ rval->object_type = object_type;
+ rval->datatype = NULL;
+ rval->language = NULL;
+
+#if 0
+ printf("SUBJECT : %s\n", subject);
+ printf("PREDICATE: %s\n", predicate);
+ printf("OBJECT : %s\n", object);
+ printf("DATATYPE : %s\n", datatype);
+ printf("LANG : %s\n", language);
+#endif
+
+ /* a triple needs a subject, predicate and object at minimum to be
+ * considered a triple. */
+ if((subject != NULL) && (predicate != NULL) && (object != NULL))
+ {
+ rval->subject = rdfa_replace_string(rval->subject, subject);
+ rval->predicate = rdfa_replace_string(rval->predicate, predicate);
+ rval->object = rdfa_replace_string(rval->object, object);
+
+ /* if the datatype is present, set it */
+ if(datatype != NULL)
+ {
+ rval->datatype = rdfa_replace_string(rval->datatype, datatype);
+ }
+
+ /* if the language was specified, set it */
+ if(language != NULL)
+ {
+ rval->language = rdfa_replace_string(rval->language, language);
+ }
+ }
+
+ return rval;
+}
+
+void rdfa_print_triple(rdftriple* triple)
+{
+ if(triple->object_type == RDF_TYPE_NAMESPACE_PREFIX)
+ {
+ printf("%s %s: <%s> .\n",
+ triple->subject, triple->predicate, triple->object);
+ }
+ else
+ {
+ if(triple->subject != NULL)
+ {
+ if((triple->subject[0] == '_') && (triple->subject[1] == ':'))
+ {
+ printf("%s\n", triple->subject);
+ }
+ else
+ {
+ printf("<%s>\n", triple->subject);
+ }
+ }
+ else
+ {
+ printf("INCOMPLETE\n");
+ }
+
+ if(triple->predicate != NULL)
+ {
+ printf(" <%s>\n", triple->predicate);
+ }
+ else
+ {
+ printf(" INCOMPLETE\n");
+ }
+
+ if(triple->object != NULL)
+ {
+ if(triple->object_type == RDF_TYPE_IRI)
+ {
+ if((triple->object[0] == '_') && (triple->object[1] == ':'))
+ {
+ printf(" %s", triple->object);
+ }
+ else
+ {
+ printf(" <%s>", triple->object);
+ }
+ }
+ else if(triple->object_type == RDF_TYPE_PLAIN_LITERAL)
+ {
+ printf(" \"%s\"", triple->object);
+ if(triple->language != NULL)
+ {
+ printf("@%s", triple->language);
+ }
+ }
+ else if(triple->object_type == RDF_TYPE_XML_LITERAL)
+ {
+ printf(" \"%s\"^^rdf:XMLLiteral", triple->object);
+ }
+ else if(triple->object_type == RDF_TYPE_TYPED_LITERAL)
+ {
+ if((triple->datatype != NULL) && (triple->language != NULL))
+ {
+ printf(" \"%s\"@%s^^<%s>",
+ triple->object, triple->language, triple->datatype);
+ }
+ else if(triple->datatype != NULL)
+ {
+ printf(" \"%s\"^^<%s>", triple->object, triple->datatype);
+ }
+ }
+ else
+ {
+ printf(" <%s> <---- UNKNOWN OBJECT TYPE", triple->object);
+ }
+
+ printf(" .\n");
+ }
+ else
+ {
+ printf(" INCOMPLETE .");
+ }
+ }
+}
+
+void rdfa_free_triple(rdftriple* triple)
+{
+ free(triple->subject);
+ free(triple->predicate);
+ free(triple->object);
+ free(triple->datatype);
+ free(triple->language);
+ free(triple);
+}
+
+#ifndef LIBRDFA_IN_RAPTOR
+/**
+ * Generates a namespace prefix triple for any application that is
+ * interested in processing namespace changes.
+ *
+ * @param context the RDFa context.
+ * @param prefix the name of the prefix
+ * @param IRI the fully qualified IRI that the prefix maps to.
+ */
+void rdfa_generate_namespace_triple(
+ rdfacontext* context, const char* prefix, const char* iri)
+{
+ if(context->processor_graph_triple_callback != NULL)
+ {
+ rdftriple* triple = rdfa_create_triple(
+ "@prefix", prefix, iri, RDF_TYPE_NAMESPACE_PREFIX, NULL, NULL);
+ context->processor_graph_triple_callback(triple, context->callback_data);
+ }
+}
+
+/**
+ * Generates a set of triples that describe the location of a warning or
+ * error in a document.
+ *
+ * @param context the currently active context.
+ * @param subject the name of the subject that is associated with the triples.
+ */
+#if 1 /* remove when the prototype is in the header */
+void rdfa_processor_location_triples(rdfacontext* context, const char* subject);
+#endif
+void rdfa_processor_location_triples(rdfacontext* context, const char* subject)
+{
+}
+
+/**
+ * Generates a set of triples in the processor graph including the processor's
+ * position in the byte stream.
+ *
+ * @param context the current active context.
+ * @param type the type of the message, which may be any of the RDF Classes
+ * defined in the RDFa Core specification:
+ * http://www.w3.org/TR/rdfa-core/#processor-graph-reporting
+ * @param msg the message associated with the processor warning.
+ */
+void rdfa_processor_triples(
+ rdfacontext* context, const char* type, const char* msg)
+{
+ if(context->processor_graph_triple_callback != NULL)
+ {
+ char buffer[32];
+ char* subject = rdfa_create_bnode(context);
+ char* context_subject = rdfa_create_bnode(context);
+
+ /* generate the RDFa Processing Graph warning type triple */
+ rdftriple* triple = rdfa_create_triple(
+ subject, "http://www.w3.org/1999/02/22-rdf-syntax-ns#type",
+ type, RDF_TYPE_IRI, NULL, NULL);
+ context->processor_graph_triple_callback(triple, context->callback_data);
+
+ /* generate the description */
+ triple = rdfa_create_triple(
+ subject, "http://purl.org/dc/terms/description", msg,
+ RDF_TYPE_PLAIN_LITERAL, NULL, "en");
+ context->processor_graph_triple_callback(triple, context->callback_data);
+
+ /* generate the context triple for the error */
+ triple = rdfa_create_triple(
+ subject, "http://www.w3.org/ns/rdfa#context",
+ context_subject, RDF_TYPE_IRI, NULL, NULL);
+ context->processor_graph_triple_callback(triple, context->callback_data);
+
+ /* generate the type for the context triple */
+ triple = rdfa_create_triple(
+ context_subject, "http://www.w3.org/1999/02/22-rdf-syntax-ns#type",
+ "http://www.w3.org/2009/pointers#LineCharPointer",
+ RDF_TYPE_IRI, NULL, NULL);
+ context->processor_graph_triple_callback(triple, context->callback_data);
+
+ /* generate the line number */
+ snprintf(buffer, sizeof(buffer) - 1, "%d",
+ (int)xmlSAX2GetLineNumber(context->parser));
+ triple = rdfa_create_triple(
+ context_subject, "http://www.w3.org/2009/pointers#lineNumber",
+ buffer, RDF_TYPE_TYPED_LITERAL,
+ "http://www.w3.org/2001/XMLSchema#positiveInteger", NULL);
+ context->processor_graph_triple_callback(triple, context->callback_data);
+
+ free(context_subject);
+ free(subject);
+ }
+}
+#endif
+
+/**
+ * Completes all incomplete triples that are part of the current
+ * context by matching the new_subject with the list of incomplete
+ * triple predicates.
+ *
+ * @param context the RDFa context.
+ */
+void rdfa_complete_incomplete_triples(rdfacontext* context)
+{
+ /* 10. If the [ skip element ] flag is 'false', and [ new subject ]
+ * was set to a non-null value, then any [ incomplete triple ]s
+ * within the current context should be completed:
+ *
+ * The [ list of incomplete triples ] from the current [ evaluation
+ * context ] ( not the [ local list of incomplete triples ]) will
+ * contain zero or more predicate URIs. This list is iterated, and
+ * each of the predicates is used with [ parent subject ] and
+ * [ new subject ] to generate a triple. Note that at each level
+ * there are two , lists of [ incomplete triple ]s; one for the
+ * current processing level (which is passed to each child element
+ * in the previous step), and one that was received as part of the
+ * [ evaluation context ]. It is the latter that is used in
+ * processing during this step. */
+ unsigned int i;
+ for(i = 0; i < context->incomplete_triples->num_items; i++)
+ {
+ rdfalist* incomplete_triples = context->incomplete_triples;
+ rdfalistitem* incomplete_triple = incomplete_triples->items[i];
+
+ if(incomplete_triple->flags & RDFALIST_FLAG_DIR_NONE)
+ {
+ /* If direction is 'none', the new subject is added to the list
+ * from the iterated incomplete triple. */
+ const char* predicate = (const char*)incomplete_triple->data;
+ rdftriple* triple = rdfa_create_triple(context->parent_subject,
+ predicate, context->new_subject, RDF_TYPE_IRI, NULL, NULL);
+
+ /* ensure the list mapping exists */
+ rdfa_create_list_mapping(
+ context, context->local_list_mappings,
+ context->parent_subject, predicate);
+
+ /* add the predicate to the list mapping */
+ rdfa_append_to_list_mapping(context->local_list_mappings,
+ context->parent_subject, predicate, (void*)triple);
+ }
+ else if(incomplete_triple->flags & RDFALIST_FLAG_DIR_FORWARD)
+ {
+ /* If [direction] is 'forward' then the following triple is generated:
+ *
+ * subject
+ * [parent subject]
+ * predicate
+ * the predicate from the iterated incomplete triple
+ * object
+ * [new subject] */
+ rdftriple* triple =
+ rdfa_create_triple(context->parent_subject,
+ (const char*)incomplete_triple->data, context->new_subject,
+ RDF_TYPE_IRI, NULL, NULL);
+ context->default_graph_triple_callback(triple, context->callback_data);
+ }
+ else
+ {
+ /* If [direction] is not 'forward' then this is the triple generated:
+ *
+ * subject
+ * [new subject]
+ * predicate
+ * the predicate from the iterated incomplete triple
+ * object
+ * [parent subject] */
+ rdftriple* triple =
+ rdfa_create_triple(context->new_subject,
+ (const char*)incomplete_triple->data, context->parent_subject,
+ RDF_TYPE_IRI, NULL, NULL);
+ context->default_graph_triple_callback(triple, context->callback_data);
+ }
+ free(incomplete_triple->data);
+ free(incomplete_triple);
+ }
+ context->incomplete_triples->num_items = 0;
+}
+
+void rdfa_complete_type_triples(
+ rdfacontext* context, const rdfalist* type_of)
+{
+ unsigned int i;
+ rdfalistitem** iptr = type_of->items;
+ const char* subject;
+ const char* type;
+
+ if(context->rdfa_version == RDFA_VERSION_1_0)
+ {
+ /* RDFa 1.0: 6.1 One or more 'types' for the [new subject] can be set by
+ * using @type_of. If present, the attribute must contain one or
+ * more URIs, obtained according to the section on URI and CURIE
+ * Processing, each of which is used to generate a triple as follows:
+ *
+ * subject
+ * [new subject]
+ * predicate
+ * http://www.w3.org/1999/02/22-rdf-syntax-ns#type
+ * object
+ * full URI of 'type'
+ */
+ subject = context->new_subject;
+ }
+ else
+ {
+ /* RDFa 1.1: 7. One or more 'types' for the typed resource can be set by
+ * using @typeof. If present, the attribute may contain one or more IRIs,
+ * obtained according to the section on CURIE and IRI Processing, each of
+ * which is used to generate a triple as follows:
+ *
+ * subject
+ * typed resource
+ * predicate
+ * http://www.w3.org/1999/02/22-rdf-syntax-ns#type
+ * object
+ * current full IRI of 'type' from typed resource
+ */
+ subject = context->typed_resource;
+ }
+
+ for(i = 0; i < type_of->num_items; i++)
+ {
+ rdfalistitem* iri = *iptr;
+ rdftriple* triple;
+ type = (const char*)iri->data;
+
+ triple = rdfa_create_triple(subject,
+ "http://www.w3.org/1999/02/22-rdf-syntax-ns#type", type, RDF_TYPE_IRI,
+ NULL, NULL);
+
+ context->default_graph_triple_callback(triple, context->callback_data);
+ iptr++;
+ }
+}
+
+void rdfa_complete_relrev_triples(
+ rdfacontext* context, const rdfalist* rel, const rdfalist* rev)
+{
+ /* 7. If in any of the previous steps a [current object resource]
+ * was set to a non-null value, it is now used to generate triples */
+ unsigned int i;
+
+ /* Predicates for the [current object resource] can be set by using
+ * one or both of the @rel and @rev attributes. */
+
+ /* If present, @rel will contain one or more URIs, obtained
+ * according to the section on CURIE and URI Processing each of
+ * which is used to generate a triple as follows:
+ *
+ * subject
+ * [new subject]
+ * predicate
+ * full URI
+ * object
+ * [current object resource] */
+ if(rel != NULL)
+ {
+ rdfalistitem** relptr = rel->items;
+ for(i = 0; i < rel->num_items; i++)
+ {
+ rdfalistitem* curie = *relptr;
+
+ rdftriple* triple = rdfa_create_triple(context->new_subject,
+ (const char*)curie->data, context->current_object_resource,
+ RDF_TYPE_IRI, NULL, NULL);
+
+ context->default_graph_triple_callback(triple, context->callback_data);
+ relptr++;
+ }
+ }
+
+ /* If present, @rev will contain one or more URIs, obtained
+ * according to the section on CURIE and URI Processing each of which
+ * is used to generate a triple as follows:
+ *
+ * subject
+ * [current object resource]
+ * predicate
+ * full URI
+ * object
+ * [new subject] */
+ if(rev != NULL)
+ {
+ rdfalistitem** revptr = rev->items;
+ for(i = 0; i < rev->num_items; i++)
+ {
+ rdfalistitem* curie = *revptr;
+
+ rdftriple* triple = rdfa_create_triple(
+ context->current_object_resource, (const char*)curie->data,
+ context->new_subject, RDF_TYPE_IRI, NULL, NULL);
+
+ context->default_graph_triple_callback(triple, context->callback_data);
+ revptr++;
+ }
+ }
+}
+
+void rdfa_save_incomplete_triples(
+ rdfacontext* context, const rdfalist* rel, const rdfalist* rev)
+{
+ unsigned int i;
+ /* 8. If however [current object resource] was set to null, but
+ * there are predicates present, then they must be stored as
+ * [incomplete triple]s, pending the discovery of a subject that
+ * can be used as the object. Also, [current object resource]
+ * should be set to a newly created [bnode] */
+ if(context->current_object_resource == NULL)
+ {
+ context->current_object_resource = rdfa_create_bnode(context);
+ }
+
+ /* If present, @rel must contain one or more URIs, obtained
+ * according to the section on CURIE and URI Processing each of
+ * which is added to the [local local list of incomplete triples]
+ * as follows:
+ *
+ * predicate
+ * full URI
+ * direction
+ * forward */
+ if(rel != NULL)
+ {
+ rdfalistitem** relptr = rel->items;
+ for(i = 0; i < rel->num_items; i++)
+ {
+ rdfalistitem* curie = *relptr;
+
+ rdfa_add_item(
+ context->local_incomplete_triples, curie->data,
+ (liflag_t)(RDFALIST_FLAG_DIR_FORWARD | RDFALIST_FLAG_TEXT));
+
+ relptr++;
+ }
+ }
+
+ /* If present, @rev must contain one or more URIs, obtained
+ * according to the section on CURIE and URI Processing, each of
+ * which is added to the [local list of incomplete triples] as follows:
+ *
+ * predicate
+ * full URI
+ * direction
+ * reverse */
+ if(rev != NULL)
+ {
+ rdfalistitem** revptr = rev->items;
+ for(i = 0; i < rev->num_items; i++)
+ {
+ rdfalistitem* curie = *revptr;
+
+ rdfa_add_item(
+ context->local_incomplete_triples, curie->data,
+ (liflag_t)(RDFALIST_FLAG_DIR_REVERSE | RDFALIST_FLAG_TEXT));
+
+ revptr++;
+ }
+ }
+}
+
+void rdfa_complete_object_literal_triples(rdfacontext* context)
+{
+ /* 9. The next step of the iteration is to establish any
+ * [current object literal];
+ *
+ * Predicates for the [current object literal] can be set by using
+ * @property. If present, a URI is obtained according to the
+ * section on CURIE and URI Processing, and then the actual literal
+ * value is obtained as follows: */
+ const char* current_object_literal = NULL;
+ rdfresource_t type = RDF_TYPE_UNKNOWN;
+
+ unsigned int i;
+ rdfalistitem** pptr;
+
+ /* * as a [plain literal] if:
+ * o @content is present;
+ * o or all children of the [current element] are text nodes;
+ * o or there are no child nodes; TODO: Is this needed?
+ * o or the body of the [current element] does have non-text
+ * child nodes but @datatype is present, with an empty value.
+ *
+ * Additionally, if there is a value for [current language] then
+ * the value of the [plain literal] should include this language
+ * information, as described in [RDF-CONCEPTS]. The actual literal
+ * is either the value of @content (if present) or a string created
+ * by concatenating the text content of each of the descendant
+ * elements of the [current element] in document order. */
+ if((context->content != NULL))
+ {
+ current_object_literal = context->content;
+ type = RDF_TYPE_PLAIN_LITERAL;
+ }
+ else if(context->xml_literal && strchr(context->xml_literal, '<') == NULL)
+ {
+ current_object_literal = context->plain_literal;
+ type = RDF_TYPE_PLAIN_LITERAL;
+ }
+ else if(strlen(context->plain_literal) == 0)
+ {
+ current_object_literal = (const char*)"";
+ type = RDF_TYPE_PLAIN_LITERAL;
+ }
+ else if((context->xml_literal != NULL) &&
+ (context->datatype != NULL) &&
+ (strlen(context->xml_literal) > 0) &&
+ (strcmp(context->datatype, "") == 0))
+ {
+ current_object_literal = context->plain_literal;
+ type = RDF_TYPE_PLAIN_LITERAL;
+ }
+
+
+ /* * as an [XML literal] if:
+ * o the [current element] has any child nodes that are not
+ * simply text nodes, and @datatype is not present, or is
+ * present, but is set to rdf:XMLLiteral.
+ *
+ * The value of the [XML literal] is a string created by
+ * serializing to text, all nodes that are descendants of the
+ * [current element], i.e., not including the element itself, and
+ * giving it a datatype of rdf:XMLLiteral. */
+ if((context->xml_literal != NULL) &&
+ (current_object_literal == NULL) &&
+ (strchr(context->xml_literal, '<') != NULL) &&
+ ((context->datatype == NULL) ||
+ (strcmp(context->datatype,
+ "http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral") == 0)))
+ {
+ current_object_literal = context->xml_literal;
+ type = RDF_TYPE_XML_LITERAL;
+ }
+
+ /* * as a [typed literal] if:
+ * o @datatype is present, and does not have an empty
+ * value.
+ *
+ * The actual literal is either the value of @content (if present)
+ * or a string created by concatenating the value of all descendant
+ * text nodes, of the [current element] in turn. The final string
+ * includes the datatype URI, as described in [RDF-CONCEPTS], which
+ * will have been obtained according to the section on CURIE and
+ * URI Processing. */
+ if((context->datatype != NULL) && (strlen(context->datatype) > 0))
+ {
+ if(context->content != NULL)
+ {
+ /* Static code analyzer clang says next line is not needed;
+ * "Assigned value is always the same as the existing value"
+ */
+ /* current_object_literal = context->content; */
+ type = RDF_TYPE_TYPED_LITERAL;
+ }
+ else if(strcmp(context->datatype,
+ "http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral") != 0)
+ {
+ current_object_literal = context->plain_literal;
+ type = RDF_TYPE_TYPED_LITERAL;
+ }
+ }
+
+ /* TODO: Setting the current object literal to the plain literal in
+ * the case of xsd:string isn't mentioned in the syntax
+ * processing document. */
+ if((current_object_literal == NULL) && (context->datatype != NULL) &&
+ (strcmp(
+ context->datatype, "http://www.w3.org/2001/XMLSchema#string") == 0))
+ {
+ current_object_literal = context->plain_literal;
+ type = RDF_TYPE_TYPED_LITERAL;
+ }
+
+ /* The [current object literal] is then used with each predicate to
+ * generate a triple as follows:
+ *
+ * subject
+ * [new subject]
+ * predicate
+ * full URI
+ * object
+ * [current object literal] */
+ pptr = context->property->items;
+ for(i = 0; i < context->property->num_items; i++)
+ {
+
+ rdfalistitem* curie = *pptr;
+ rdftriple* triple = NULL;
+
+ triple = rdfa_create_triple(context->new_subject,
+ (const char*)curie->data, current_object_literal, type,
+ context->datatype, context->language);
+
+ context->default_graph_triple_callback(triple, context->callback_data);
+ pptr++;
+ }
+
+ /* TODO: Implement recurse flag being set to false
+ *
+ * Once the triple has been created, if the [datatype] of the
+ * [current object literal] is rdf:XMLLiteral, then the [recurse]
+ * flag is set to false */
+ context->recurse = 0;
+}
+
+void rdfa_complete_current_property_value_triples(rdfacontext* context)
+{
+ /* 11. The next step of the iteration is to establish any current property
+ * value;
+ * Predicates for the current property value can be set by using @property.
+ * If present, one or more resources are obtained according to the section
+ * on CURIE and IRI Processing, and then the actual literal value is
+ * obtained as follows: */
+ char* current_property_value = NULL;
+ rdfresource_t type = RDF_TYPE_UNKNOWN;
+
+ unsigned int i;
+ rdfalistitem** pptr;
+
+ /* as a typed literal if @datatype is present, does not have an empty
+ * value according to the section on CURIE and IRI Processing, and is not
+ * set to XMLLiteral in the vocabulary
+ * http://www.w3.org/1999/02/22-rdf-syntax-ns#. */
+ if((context->datatype != NULL) && (strcmp(context->datatype,
+ "http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral") != 0))
+ {
+ /* The actual literal is either the value of @content (if present) or a
+ * string created by concatenating the value of all descendant text nodes,
+ * of the current element in turn. */
+ if(context->content != NULL)
+ {
+ current_property_value = context->content;
+ }
+ else
+ {
+ current_property_value = context->plain_literal;
+ }
+
+ /* The final string includes the datatype
+ * IRI, as described in [RDF-CONCEPTS], which will have been obtained
+ * according to the section on CURIE and IRI Processing.
+ * otherwise, as a plain literal if @datatype is present but has an
+ * empty value according to the section on CURIE and IRI Processing. */
+ if(strlen(context->datatype) > 0)
+ {
+ type = RDF_TYPE_TYPED_LITERAL;
+ }
+ else
+ {
+ type = RDF_TYPE_PLAIN_LITERAL;
+ }
+ }
+ else if((context->datatype != NULL) && (strcmp(context->datatype,
+ "http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral") == 0))
+ {
+ /* otherwise, as an XML literal if @datatype is present and is set to
+ * XMLLiteral in the vocabulary
+ * http://www.w3.org/1999/02/22-rdf-syntax-ns#.
+ * The value of the XML literal is a string created by serializing to
+ * text, all nodes that are descendants of the current element, i.e., not
+ * including the element itself, and giving it a datatype of XMLLiteral
+ * in the vocabulary http://www.w3.org/1999/02/22-rdf-syntax-ns#. The
+ * format of the resulting serialized content is as defined in Exclusive
+ * XML Canonicalization Version [XML-EXC-C14N].
+ * In order to maintain maximum portability of this literal, any children
+ * of the current node that are elements must have the current XML
+ * namespace declarations (if any) declared on the serialized element.
+ * Since the child element node could also declare new XML namespaces,
+ * the RDFa Processor must be careful to merge these together when
+ * generating the serialized element definition. For avoidance of doubt,
+ * any re-declarations on the child node must take precedence over
+ * declarations that were active on the current node. */
+ current_property_value = context->xml_literal;
+ type = RDF_TYPE_XML_LITERAL;
+ }
+ else if(context->content != NULL)
+ {
+ /* otherwise, as an plain literal using the value of @content if
+ * @content is present. */
+ current_property_value = context->content;
+ type = RDF_TYPE_PLAIN_LITERAL;
+ }
+ else if((context->rel_present == 0) && (context->rev_present == 0) &&
+ (context->content == NULL))
+ {
+ /* otherwise, if the @rel, @rev, and @content attributes are not present,
+ * as a resource obtained from one of the following: */
+ if(context->resource != NULL)
+ {
+ /* by using the resource from @resource, if present, obtained
+ * according to the section on CURIE and IRI Processing; */
+ current_property_value = context->resource;
+ type = RDF_TYPE_IRI;
+ }
+ else if(context->href != NULL)
+ {
+ /* otherwise, by using the IRI from @href, if present, obtained
+ * according to the section on CURIE and IRI Processing; */
+ current_property_value = context->href;
+ type = RDF_TYPE_IRI;
+ }
+ else if(context->src != NULL)
+ {
+ /* otherwise, by using the IRI from @src, if present, obtained
+ * according to the section on CURIE and IRI Processing. */
+ current_property_value = context->src;
+ type = RDF_TYPE_IRI;
+ }
+ else if((context->about == NULL) && (context->typed_resource != NULL))
+ {
+ /* otherwise, if @typeof is present and @about is not, the value of
+ * typed resource. */
+ current_property_value = context->typed_resource;
+ type = RDF_TYPE_IRI;
+ }
+ else
+ {
+ /* otherwise as a plain literal. */
+ current_property_value = context->plain_literal;
+ type = RDF_TYPE_PLAIN_LITERAL;
+ }
+ }
+ else
+ {
+ /* otherwise as a plain literal. */
+ current_property_value = context->plain_literal;
+ type = RDF_TYPE_PLAIN_LITERAL;
+ }
+
+ /* Additionally, if there is a value for current language then the value
+ * of the plain literal should include this language information, as
+ * described in [RDF-CONCEPTS]. The actual literal is either the value
+ * of @content (if present) or a string created by concatenating the text
+ * content of each of the descendant elements of the current element in
+ * document order.
+ *
+ * NOTE: This happens automatically due to the way the code is setup. */
+
+ if(context->inlist_present)
+ {
+ /* The current property value is then used with each predicate as
+ * follows:
+ * If the element also includes the @inlist attribute, the current
+ * property value is added to the local list mapping as follows:
+ * if the local list mapping does not contain a list associated with
+ * the predicate IRI, instantiate a new list and add to local list
+ * mappings add the current property value to the list associated
+ * with the predicate IRI in the local list mapping */
+ rdfa_establish_new_inlist_triples(
+ context, context->property, current_property_value, type);
+ }
+ else
+ {
+ pptr = context->property->items;
+ for(i = 0; i < context->property->num_items; i++)
+ {
+ /* Otherwise the current property value is used to generate a triple
+ * as follows:
+ * subject
+ * new subject
+ * predicate
+ * full IRI
+ * object
+ * current property value */
+ rdfalistitem* curie = *pptr;
+ rdftriple* triple = rdfa_create_triple(context->new_subject,
+ (const char*)curie->data, current_property_value, type,
+ context->datatype, context->language);
+
+ context->default_graph_triple_callback(triple, context->callback_data);
+
+ pptr++;
+ }
+ }
+}