Exemple #1
0
/**
 * 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;
}
Exemple #2
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++;
   }
}
Exemple #3
0
/**
 * 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);
   }
}
Exemple #4
0
/**
 * 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);
}
Exemple #5
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++;
   }
}
Exemple #6
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++;
      }
   }
}
Exemple #7
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(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;
}
Exemple #8
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++;
      }
   }
}
Exemple #9
0
/**
 * 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;
}
Exemple #10
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;
}
Exemple #11
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);
}