/** * 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_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); } context->incomplete_triples->num_items = 0; }
void rdfa_complete_type_triples( rdfacontext* context, const rdfalist* type_of) { // 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' unsigned int i; rdfalistitem** iptr = type_of->items; for(i = 0; i < type_of->num_items; i++) { rdfalistitem* curie = *iptr; rdftriple* triple = rdfa_create_triple(context->new_subject, "http://www.w3.org/1999/02/22-rdf-syntax-ns#type", (const char*)curie->data, RDF_TYPE_IRI, NULL, NULL); context->default_graph_triple_callback(triple, context->callback_data); iptr++; } }
/** * 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); } }
/** * 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) { rdftriple* triple = rdfa_create_triple( "@prefix", prefix, iri, RDF_TYPE_NAMESPACE_PREFIX, NULL, NULL); if(context->processor_graph_triple_callback) context->processor_graph_triple_callback(triple, context->callback_data); }
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_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++; } } }
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: */ 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 = (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_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++; } } }
/** * 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_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: 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(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 = (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((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) { 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; }
/** * Handles the start_element call */ static void start_element(void *parser_context, const char* name, const char* prefix, const char* URI, int nb_namespaces, const char** namespaces, int nb_attributes, int nb_defaulted, const char** attributes) { rdfacontext* root_context = (rdfacontext*)parser_context; rdfalist* context_stack = (rdfalist*)root_context->context_stack; rdfacontext* context = rdfa_create_new_element_context(context_stack); char* xml_lang = NULL; const char* about_curie = NULL; char* about = NULL; const char* src_curie = NULL; char* src = NULL; const char* type_of_curie = NULL; rdfalist* type_of = NULL; const char* rel_curie = NULL; rdfalist* rel = NULL; const char* rev_curie = NULL; rdfalist* rev = NULL; const char* property_curie = NULL; rdfalist* property = NULL; const char* resource_curie = NULL; char* resource = NULL; const char* href_curie = NULL; char* href = NULL; char* content = NULL; const char* datatype_curie = NULL; char* datatype = NULL; #ifdef LIBRDFA_IN_RAPTOR if(1) { raptor_parser* rdf_parser = (raptor_parser*)context->callback_data; raptor_sax2_update_document_locator(context->sax2, &rdf_parser->locator); } #endif rdfa_push_item(context_stack, context, RDFALIST_FLAG_CONTEXT); #if defined(DEBUG) && DEBUG > 0 if(1) { int i; /* dump all arguments sent to this callback */ fprintf(stdout, "DEBUG: SAX.startElementNs(%s", (char *) name); if (prefix == NULL) fprintf(stdout, ", NULL"); else fprintf(stdout, ", %s", (char *) prefix); if (URI == NULL) fprintf(stdout, ", NULL"); else fprintf(stdout, ", '%s'", (char *) URI); fprintf(stdout, ", %d", nb_namespaces); /* dump all namespaces */ if (namespaces != NULL) { for (i = 0;i < nb_namespaces * 2;i++) { fprintf(stdout, ", xmlns"); if (namespaces[i] != NULL) fprintf(stdout, ":%s", namespaces[i]); i++; fprintf(stdout, "='%s'", namespaces[i]); } } /* dump all attributes */ fprintf(stdout, ", %d, %d", nb_attributes, nb_defaulted); if (attributes != NULL) { for (i = 0;i < nb_attributes * 5;i += 5) { if (attributes[i + 1] != NULL) fprintf( stdout, ", %s:%s='", attributes[i + 1], attributes[i]); else fprintf(stdout, ", %s='", attributes[i]); fprintf(stdout, "%.4s...', %d", attributes[i + 3], (int)(attributes[i + 4] - attributes[i + 3])); } } fprintf(stdout, ")\n"); } #endif /* start the XML Literal text */ if(context->xml_literal == NULL) { context->xml_literal = rdfa_replace_string(context->xml_literal, "<"); context->xml_literal_size = 1; } else { context->xml_literal = rdfa_n_append_string( context->xml_literal, &context->xml_literal_size, "<", 1); } context->xml_literal = rdfa_n_append_string( context->xml_literal, &context->xml_literal_size, name, strlen(name)); if(!context->xml_literal_namespaces_defined) { /* append namespaces to XML Literal */ #ifdef LIBRDFA_IN_RAPTOR raptor_namespace_stack* nstack = &context->sax2->namespaces; raptor_namespace* ns; raptor_namespace** ns_list = NULL; size_t ns_size; #else void** umap = context->uri_mappings; #endif char* umap_key = NULL; void* umap_value = NULL; /* if the namespaces are not defined, then neither is the xml:lang */ context->xml_literal_xml_lang_defined = 0; #ifdef LIBRDFA_IN_RAPTOR ns_size = 0; ns_list = raptor_namespace_stack_to_array(nstack, &ns_size); qsort((void*)ns_list, ns_size, sizeof(raptor_namespace*), raptor_nspace_compare); while(ns_size > 0) #else while(*umap != NULL) #endif { unsigned char insert_xmlns_definition = 1; const char* attr = NULL; /* get the next mapping to process */ #ifdef LIBRDFA_IN_RAPTOR ns=ns_list[--ns_size]; umap_key = (char*)raptor_namespace_get_prefix(ns); if(!umap_key) umap_key=(char*)XMLNS_DEFAULT_MAPPING; umap_value = (char*)raptor_uri_as_string(raptor_namespace_get_uri(ns)); #else rdfa_next_mapping(umap++, &umap_key, &umap_value); umap++; #endif /* check to make sure that the namespace isn't already * defined in the current element. */ if(attributes != NULL) { const char** attrs = attributes; while((*attrs != NULL) && insert_xmlns_definition) { attr = *attrs++; /* if the attribute is a umap_key, skip the definition * of the attribute. */ if(strcmp(attr, umap_key) == 0) { insert_xmlns_definition = 0; } } } /* if the namespace isn't already defined on the element, * copy it to the XML Literal string. */ if(insert_xmlns_definition) { /* append the namespace attribute to the XML Literal */ context->xml_literal = rdfa_n_append_string( context->xml_literal, &context->xml_literal_size, " xmlns", strlen(" xmlns")); /* check to see if we're dumping the standard XHTML namespace or * a user-defined XML namespace */ if(strcmp(umap_key, XMLNS_DEFAULT_MAPPING) != 0) { context->xml_literal = rdfa_n_append_string( context->xml_literal, &context->xml_literal_size, ":", 1); context->xml_literal = rdfa_n_append_string( context->xml_literal, &context->xml_literal_size, umap_key, strlen(umap_key)); } /* append the namespace value */ context->xml_literal = rdfa_n_append_string( context->xml_literal, &context->xml_literal_size, "=\"", 2); context->xml_literal = rdfa_n_append_string( context->xml_literal, &context->xml_literal_size, (const char*)umap_value, strlen((char*)umap_value)); context->xml_literal = rdfa_n_append_string( context->xml_literal, &context->xml_literal_size, "\"", 1); } } /* end while umap not NULL */ context->xml_literal_namespaces_defined = 1; #ifdef LIBRDFA_IN_RAPTOR if(ns_list) raptor_free_memory(ns_list); #endif } /* end if namespaces inserted */ #ifdef LIBRDFA_IN_RAPTOR /* Raptor namespace code does this already */ #else /* 3. For backward compatibility, RDFa Processors should also permit the * definition of mappings via @xmlns. In this case, the value to be mapped * is set by the XML namespace prefix, and the value to map is the value of * the attribute - an IRI. (Note that prefix mapping via @xmlns is * deprecated, and may be removed in a future version of this * specification.) When xmlns is supported, such mappings must be processed * before processing any mappings from @prefix on the same element. */ if(namespaces != NULL) { int ni; for(ni = 0; ni < nb_namespaces * 2; ni += 2) { const char* ns = namespaces[ni]; const char* value = namespaces[ni + 1]; /* Regardless of how the mapping is declared, the value to be mapped * must be converted to lower case, and the IRI is not processed in * any way; in particular if it is a relative path it must not be * resolved against the current base. */ char* lcns = NULL; if(ns != NULL) { /* convert the namespace string to lowercase */ unsigned int i; size_t ns_length = strlen(ns); lcns = (char*)malloc(ns_length + 1); for(i = 0; i <= ns_length; i++) { lcns[i] = tolower(ns[i]); } } /* update the URI mappings */ rdfa_update_uri_mappings(context, lcns, value); if(lcns != NULL) { free(lcns); } } } #endif /* detect the RDFa version of the document, if specified */ if(attributes != NULL) { int ci; /* search for a version attribute */ for(ci = 0; ci < nb_attributes * 5; ci += 5) { const char* attr; char* value; size_t value_length = 0; attr = attributes[ci]; value_length = attributes[ci + 4] - attributes[ci + 3] + 1; if(strcmp(attr, "version") == 0) { /* append the attribute-value pair to the XML literal */ value = (char*)malloc(value_length + 1); snprintf(value, value_length, "%s", attributes[ci + 3]); if(strstr(value, "RDFa 1.0") != NULL) { context->rdfa_version = RDFA_VERSION_1_0; } else if(strstr(value, "RDFa 1.1") != NULL) { context->rdfa_version = RDFA_VERSION_1_1; } free(value); } } } #ifdef LIBRDFA_IN_RAPTOR if(context->sax2) { /* Raptor handles xml:lang itself but not 'lang' */ xml_lang = (char*)raptor_sax2_inscope_xml_language(context->sax2); xml_lang = rdfa_replace_string(NULL, xml_lang); } #endif /* prepare all of the RDFa-specific attributes we are looking for. * scan all of the attributes for the RDFa-specific attributes */ if(attributes != NULL) { int ci; if(context->rdfa_version == RDFA_VERSION_1_1) { /* process all vocab and prefix attributes */ for(ci = 0; ci < nb_attributes * 5; ci += 5) { const char* attr; char* value; size_t value_length = 0; attr = attributes[ci]; value_length = attributes[ci + 4] - attributes[ci + 3] + 1; /* append the attribute-value pair to the XML literal */ value = (char*)malloc(value_length + 1); snprintf(value, value_length, "%s", attributes[ci + 3]); /* 2. Next the current element is examined for any change to the * default vocabulary via @vocab. */ if(strcmp(attr, "vocab") == 0) { if(strlen(value) < 1) { /* If the value is empty, then the local default vocabulary * must be reset to the Host Language defined default * (if any). */ free(context->default_vocabulary); context->default_vocabulary = NULL; } else { char* resolved_uri; rdftriple* triple; /* If @vocab is present and contains a value, the local * default vocabulary is updated according to the * section on CURIE and IRI Processing. */ resolved_uri = rdfa_resolve_uri(context, value); context->default_vocabulary = rdfa_replace_string( context->default_vocabulary, resolved_uri); /* The value of @vocab is used to generate a triple */ triple = rdfa_create_triple( context->base, "http://www.w3.org/ns/rdfa#usesVocabulary", resolved_uri, RDF_TYPE_IRI, NULL, NULL); context->default_graph_triple_callback( triple, context->callback_data); free(resolved_uri); } } else if(strcmp(attr, "prefix") == 0) { /* Mappings are defined via @prefix. */ char* working_string = NULL; char* atprefix = NULL; char* iri = NULL; char* saveptr = NULL; working_string = rdfa_replace_string(working_string, value); /* Values in this attribute are evaluated from beginning to * end (e.g., left to right in typical documents). */ atprefix = strtok_r(working_string, ":", &saveptr); while(atprefix != NULL) { /* find the prefix and IRI mappings while skipping whitespace */ while((*saveptr == ' ' || *saveptr == '\n' || *saveptr == '\r' || *saveptr == '\t' || *saveptr == '\f' || *saveptr == '\v') && *saveptr != '\0') { saveptr++; } iri = strtok_r(NULL, RDFA_WHITESPACE, &saveptr); /* update the prefix mappings */ rdfa_update_uri_mappings(context, atprefix, iri); if(!saveptr) break; while((*saveptr == ' ' || *saveptr == '\n' || *saveptr == '\r' || *saveptr == '\t' || *saveptr == '\f' || *saveptr == '\v') && *saveptr != '\0') { saveptr++; } /* get the next prefix to process */ atprefix = strtok_r(NULL, ":", &saveptr); } free(working_string); } else if(strcmp(attr, "inlist") == 0) { context->inlist_present = 1; } free(value); } } /* resolve all of the other RDFa values */ for(ci = 0; ci < nb_attributes * 5; ci += 5) { const char* attr; char* value; char* attrns; char* literal_text; size_t value_length = 0; attr = attributes[ci]; attrns = (char*)attributes[ci + 1]; value_length = attributes[ci + 4] - attributes[ci + 3] + 1; /* append the attribute-value pair to the XML literal */ value = (char*)malloc(value_length + 1); literal_text = (char*)malloc(strlen(attr) + value_length + 5); snprintf(value, value_length, "%s", attributes[ci + 3]); sprintf(literal_text, " %s=\"%s\"", attr, value); context->xml_literal = rdfa_n_append_string( context->xml_literal, &context->xml_literal_size, literal_text, strlen(literal_text)); free(literal_text); /* if xml:lang is defined, ensure that it is not overwritten */ if(attrns != NULL && strcmp(attrns, "xml") == 0 && strcmp(attr, "lang") == 0) { context->xml_literal_xml_lang_defined = 1; } /* process all of the RDFa attributes */ if(strcmp(attr, "about") == 0) { about_curie = value; about = rdfa_resolve_curie( context, about_curie, CURIE_PARSE_ABOUT_RESOURCE); } else if(strcmp(attr, "src") == 0) { src_curie = value; src = rdfa_resolve_curie(context, src_curie, CURIE_PARSE_HREF_SRC); } else if(strcmp(attr, "typeof") == 0) { type_of_curie = value; type_of = rdfa_resolve_curie_list( context, type_of_curie, CURIE_PARSE_INSTANCEOF_DATATYPE); } else if(strcmp(attr, "rel") == 0) { context->rel_present = 1; rel_curie = value; rel = rdfa_resolve_curie_list( context, rel_curie, CURIE_PARSE_RELREV); } else if(strcmp(attr, "rev") == 0) { context->rev_present = 1; rev_curie = value; rev = rdfa_resolve_curie_list( context, rev_curie, CURIE_PARSE_RELREV); } else if(strcmp(attr, "property") == 0) { property_curie = value; property = rdfa_resolve_curie_list( context, property_curie, CURIE_PARSE_PROPERTY); } else if(strcmp(attr, "resource") == 0) { resource_curie = value; resource = rdfa_resolve_curie( context, resource_curie, CURIE_PARSE_ABOUT_RESOURCE); } else if(strcmp(attr, "href") == 0) { href_curie = value; href = rdfa_resolve_curie(context, href_curie, CURIE_PARSE_HREF_SRC); } else if(strcmp(attr, "content") == 0) { content = rdfa_replace_string(content, value); } else if(strcmp(attr, "datatype") == 0) { datatype_curie = value; if(strlen(datatype_curie) == 0) { datatype = rdfa_replace_string(datatype, ""); } else { datatype = rdfa_resolve_curie(context, datatype_curie, CURIE_PARSE_INSTANCEOF_DATATYPE); } } else if((attrns == NULL && strcmp(attr, "lang") == 0) || (attrns != NULL && strcmp(attrns, "xml") == 0 && strcmp(attr, "lang") == 0)) { xml_lang = rdfa_replace_string(xml_lang, value); } free(value); } } /* The root element has an implicit @about declaration */ if(context->depth == 1 && about == NULL && resource == NULL && href == NULL && src == NULL) { about_curie = ""; about = rdfa_resolve_curie( context, about_curie, CURIE_PARSE_ABOUT_RESOURCE); } /* The HEAD and BODY element in XHTML and HTML has an implicit * about="" on it. */ if(about == NULL && resource == NULL && href == NULL && src == NULL && (context->parent_subject == NULL || type_of != NULL) && ((context->host_language == HOST_LANGUAGE_XHTML1 || context->host_language == HOST_LANGUAGE_HTML) && (strcasecmp(name, "head") == 0 || strcasecmp(name, "body") == 0))) { about_curie = ""; about = rdfa_resolve_curie( context, about_curie, CURIE_PARSE_ABOUT_RESOURCE); } /* check to see if we should append an xml:lang to the XML Literal * if one is defined in the context and does not exist on the * element. */ if((xml_lang == NULL) && (context->language != NULL) && !context->xml_literal_xml_lang_defined) { context->xml_literal = rdfa_n_append_string( context->xml_literal, &context->xml_literal_size, " xml:lang=\"", strlen(" xml:lang=\"")); context->xml_literal = rdfa_n_append_string( context->xml_literal, &context->xml_literal_size, context->language, strlen(context->language)); context->xml_literal = rdfa_n_append_string( context->xml_literal, &context->xml_literal_size, "\"", 1); /* ensure that the lang isn't set in a subtree (unless it's overwritten) */ context->xml_literal_xml_lang_defined = 1; } /* close the XML Literal value */ context->xml_literal = rdfa_n_append_string( context->xml_literal, &context->xml_literal_size, ">", 1); /* 3. The [current element] is also parsed for any language * information, and [language] is set in the [current * evaluation context]; */ rdfa_update_language(context, xml_lang); /***************** FOR DEBUGGING PURPOSES ONLY ******************/ #if defined(DEBUG) && DEBUG > 0 printf("DEBUG: depth = %u\n", context->depth); if(about != NULL) { printf("DEBUG: @about = %s\n", about); } if(src != NULL) { printf("DEBUG: @src = %s\n", src); } if(type_of != NULL) { printf("DEBUG: @type_of = "); rdfa_print_list(type_of); } if(context->inlist_present) { printf("DEBUG: @inlist = true\n"); } if(rel != NULL) { printf("DEBUG: @rel = "); rdfa_print_list(rel); } if(rev != NULL) { printf("DEBUG: @rev = "); rdfa_print_list(rev); } if(property != NULL) { printf("DEBUG: @property = "); rdfa_print_list(property); } if(resource != NULL) { printf("DEBUG: @resource = %s\n", resource); } if(href != NULL) { printf("DEBUG: @href = %s\n", href); } if(content != NULL) { printf("DEBUG: @content = %s\n", content); } if(datatype != NULL) { printf("DEBUG: @datatype = %s\n", datatype); } if(xml_lang != NULL) { printf("DEBUG: @xml:lang = %s\n", xml_lang); } #endif /* TODO: This isn't part of the processing model, it needs to be * included and is a correction for the last item in step #4. */ if((about == NULL) && (src == NULL) && (type_of == NULL) && (rel == NULL) && (rev == NULL) && (property == NULL) && (resource == NULL) && (href == NULL) && (context->default_vocabulary == NULL) && (prefix == NULL)) { context->skip_element = 1; } if((rel == NULL) && (rev == NULL)) { if(context->rdfa_version == RDFA_VERSION_1_0) { /* 4. If the [current element] contains no valid @rel or @rev * URI, obtained according to the section on CURIE and URI * Processing, then the next step is to establish a value for * [new subject]. Any of the attributes that can carry a * resource can set [new subject]; */ rdfa_establish_new_1_0_subject( context, name, about, src, resource, href, type_of); } else { rdfa_establish_new_1_1_subject( context, name, about, src, resource, href, type_of, property, content, datatype); } } else { if(context->rdfa_version == RDFA_VERSION_1_0) { /* 5. If the [current element] does contain a valid @rel or @rev * URI, obtained according to the section on CURIE and URI * Processing, then the next step is to establish both a value * for [new subject] and a value for [current object resource]: */ rdfa_establish_new_1_0_subject_with_relrev( context, name, about, src, resource, href, type_of); } else { rdfa_establish_new_1_1_subject_with_relrev( context, name, about, src, resource, href, type_of); } } if(context->new_subject != NULL) { #if defined(DEBUG) && DEBUG > 0 printf("DEBUG: new_subject = %s\n", context->new_subject); #endif /* RDFa 1.0: 6. If in any of the previous steps a [new subject] was set * to a non-null value, it is now used to provide a subject for * type values; */ /* RDFa 1.1: 7. If in any of the previous steps a typed resource was set * to a non-null value, it is now used to provide a subject for type * values; */ if(type_of != NULL) { rdfa_complete_type_triples(context, type_of); } /* Note that none of this block is executed if there is no * [new subject] value, i.e., [new subject] remains null. */ } if(context->current_object_resource != NULL) { /* If the element contains both the @inlist and the @rel attributes: * the @rel may contain one or more resources, obtained according to * the section on CURIE and IRI Processing each of which is used to * add an entry to the list mapping as follows: * if the local list mapping does not contain a list associated with * the IRI, instantiate a new list and add to local list mappings * add the current object resource to the list associated with the * resource in the local list mapping */ if(context->rdfa_version == RDFA_VERSION_1_1 && (rel != NULL) && context->inlist_present) { rdfresource_t object_type = RDF_TYPE_IRI; if((property != NULL) || (content != NULL)) { object_type = RDF_TYPE_PLAIN_LITERAL; if(datatype != NULL) { object_type = RDF_TYPE_TYPED_LITERAL; } } rdfa_establish_new_inlist_triples( context, rel, context->current_object_resource, object_type); } /* 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 */ rdfa_complete_relrev_triples(context, rel, rev); } if((context->current_object_resource == NULL) && context->rdfa_version == RDFA_VERSION_1_1 && (rel != NULL) && context->inlist_present) { rdfa_save_incomplete_list_triples(context, rel); } else if((context->current_object_resource == NULL) && ((rel != NULL) || (rev != NULL))) { /* 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] */ rdfa_save_incomplete_triples(context, rel, rev); } /* Ensure to re-insert XML Literal namespace information from this * point on... */ if(property != NULL) { context->xml_literal_namespaces_defined = 0; } /* save these for processing steps #9 and #10 */ context->about = rdfa_replace_string(context->about, about); context->resource = rdfa_replace_string(context->resource, resource); context->href = rdfa_replace_string(context->href, href); context->src = rdfa_replace_string(context->src, src); context->content = rdfa_replace_string(context->content, content); context->datatype = rdfa_replace_string(context->datatype, datatype); context->property = property; /* free the resolved CURIEs */ free(about); free(src); rdfa_free_list(type_of); rdfa_free_list(rel); rdfa_free_list(rev); free(xml_lang); free(content); free(resource); free(href); free(datatype); }