diff --git a/core/includes/common.inc b/core/includes/common.inc
index 00decfa..afd4baa 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -1314,8 +1314,6 @@ function format_date($timestamp, $type = 'medium', $format = '', $timezone = NUL
 /**
  * Returns an ISO8601 formatted date based on the given date.
  *
- * Callback for use within hook_rdf_mapping() implementations.
- *
  * @param $date
  *   A UNIX timestamp.
  *
diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module
index a241923..f0e80e5 100644
--- a/core/modules/comment/comment.module
+++ b/core/modules/comment/comment.module
@@ -1826,48 +1826,6 @@ function comment_ranking() {
 }
 
 /**
- * Implements hook_rdf_mapping().
- */
-function comment_rdf_mapping() {
-  return array(
-    array(
-      'type' => 'comment',
-      'bundle' => RDF_DEFAULT_BUNDLE,
-      'mapping' => array(
-        'rdftype' => array('sioc:Post', 'sioct:Comment'),
-        'title' => array(
-          'predicates' => array('dc:title'),
-        ),
-        'created' => array(
-          'predicates' => array('dc:date', 'dc:created'),
-          'datatype' => 'xsd:dateTime',
-          'callback' => 'date_iso8601',
-        ),
-        'changed' => array(
-          'predicates' => array('dc:modified'),
-          'datatype' => 'xsd:dateTime',
-          'callback' => 'date_iso8601',
-        ),
-        'comment_body' => array(
-          'predicates' => array('content:encoded'),
-        ),
-        'pid' => array(
-          'predicates' => array('sioc:reply_of'),
-          'type' => 'rel',
-        ),
-        'uid' => array(
-          'predicates' => array('sioc:has_creator'),
-          'type' => 'rel',
-        ),
-        'name' => array(
-          'predicates' => array('foaf:name'),
-        ),
-      ),
-    ),
-  );
-}
-
-/**
  * Implements hook_file_download_access().
  */
 function comment_file_download_access($field, EntityInterface $entity, File $file) {
diff --git a/core/modules/forum/config/rdf.mapping.node.forum.yml b/core/modules/forum/config/rdf.mapping.node.forum.yml
new file mode 100644
index 0000000..1b6d1c7
--- /dev/null
+++ b/core/modules/forum/config/rdf.mapping.node.forum.yml
@@ -0,0 +1,11 @@
+id: node.forum
+targetEntityType: node
+bundle: forum
+types:
+  - 'sioc:Post'
+  - 'sioct:BoardPost'
+fieldMappings:
+  taxonomy_forums:
+    properties:
+      - 'sioc:has_container'
+    mapping_type: 'rel'
diff --git a/core/modules/forum/config/rdf.mapping.taxonomy_term.forums.yml b/core/modules/forum/config/rdf.mapping.taxonomy_term.forums.yml
new file mode 100644
index 0000000..f412f6a
--- /dev/null
+++ b/core/modules/forum/config/rdf.mapping.taxonomy_term.forums.yml
@@ -0,0 +1,6 @@
+id: taxonomy_term.forums
+targetEntityType: taxonomy_term
+bundle: forums
+types:
+  - 'sioc:Container'
+  - 'sioc:Forum'
diff --git a/core/modules/forum/forum.module b/core/modules/forum/forum.module
index 42d7326..6f48e74 100644
--- a/core/modules/forum/forum.module
+++ b/core/modules/forum/forum.module
@@ -1344,29 +1344,3 @@ function _forum_update_forum_index($nid) {
       ->execute();
   }
 }
-
-/**
- * Implements hook_rdf_mapping().
- */
-function forum_rdf_mapping() {
-  return array(
-    array(
-      'type' => 'node',
-      'bundle' => 'forum',
-      'mapping' => array(
-        'rdftype' => array('sioc:Post', 'sioct:BoardPost'),
-        'taxonomy_forums' => array(
-          'predicates' => array('sioc:has_container'),
-          'type' => 'rel',
-        ),
-      ),
-    ),
-    array(
-      'type' => 'taxonomy_term',
-      'bundle' => 'forums',
-      'mapping' => array(
-        'rdftype' => array('sioc:Container', 'sioc:Forum'),
-      ),
-    ),
-  );
-}
diff --git a/core/modules/rdf/lib/Drupal/rdf/EventSubscriber/MappingSubscriber.php b/core/modules/rdf/lib/Drupal/rdf/EventSubscriber/MappingSubscriber.php
deleted file mode 100644
index 764c2f9..0000000
--- a/core/modules/rdf/lib/Drupal/rdf/EventSubscriber/MappingSubscriber.php
+++ /dev/null
@@ -1,45 +0,0 @@
-<?php
-/**
- * @file
- * Contains MappingSubscriber.
- */
-
-namespace Drupal\rdf\EventSubscriber;
-
-use Drupal\rdf\RdfMappingEvents;
-use Symfony\Component\EventDispatcher\EventSubscriberInterface;
-
-/**
- * Default RDF mapping handling.
- */
-class MappingSubscriber implements EventSubscriberInterface {
-
-  /**
-   * Stops event if incoming URI is a site schema URI.
-   *
-   * If the incoming URI is one of the site's own registered types, then
-   * mapping is unnecessary. Mapping is only necessary if the incoming type URI
-   * is from an external vocabulary.
-   *
-   * @param \Drupal\rdf\MapTypesFromInputEvent $event
-   *   The mapping event.
-   */
-  public function mapTypesFromInput(\Drupal\rdf\MapTypesFromInputEvent $event) {
-    $input_uris = $event->getInputUris();
-    $site_schema_types = $event->getSiteSchemaTypes();
-    foreach ($input_uris as $input_uri) {
-      if (isset($site_schema_types[$input_uri])) {
-        $event->setSiteSchemaUri($input_uri);
-        $event->stopPropagation();
-      }
-    }
-  }
-
-  /**
-   * Implements EventSubscriberInterface::getSubscribedEvents().
-   */
-  static function getSubscribedEvents() {
-    $events[RdfMappingEvents::MAP_TYPES_FROM_INPUT] = 'mapTypesFromInput';
-    return $events;
-  }
-}
diff --git a/core/modules/rdf/lib/Drupal/rdf/MapTypesFromInputEvent.php b/core/modules/rdf/lib/Drupal/rdf/MapTypesFromInputEvent.php
deleted file mode 100644
index c54fe0d..0000000
--- a/core/modules/rdf/lib/Drupal/rdf/MapTypesFromInputEvent.php
+++ /dev/null
@@ -1,91 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains MapInputTypesEvent.
- */
-
-namespace Drupal\rdf;
-
-use Symfony\Component\EventDispatcher\Event;
-
-/**
- * Represents type mapping as event.
- */
-class MapTypesFromInputEvent extends Event {
-
-  /**
-   * An array of incoming RDF type URIs.
-   *
-   * @var array
-   */
-  protected $inputUris;
-
-  /**
-   * An array of entity_type/bundles, keyed by site schema type URI
-   *
-   * @var array
-   */
-  protected $siteSchemaTypes;
-
-  /**
-   * The site schema type URI.
-   *
-   * @var string
-   */
-  protected $siteSchemaUri;
-
-  /**
-   * Constructor.
-   *
-   * @param $input_uris
-   *   An array of incoming RDF type URIs.
-   * @param $site_schema_types
-   *   An array of entity_type/bundles, keyed by site schema type URI.
-   */
-  public function __construct($input_uris, $site_schema_types) {
-    $this->inputUris = $input_uris;
-    $this->siteSchemaTypes = $site_schema_types;
-    $this->siteSchemaUri = FALSE;
-  }
-
-  /**
-   * Gets the input URI.
-   *
-   * @return array
-   *   The array of incoming RDF type URIs.
-   */
-  public function getInputUris() {
-    return $this->inputUris;
-  }
-
-  /**
-   * Gets the cache of internal site schema types.
-   *
-   * @return array
-   *   The cached site schema type array.
-   */
-  public function getSiteSchemaTypes() {
-    return $this->siteSchemaTypes;
-  }
-
-  /**
-   * Gets the site schema URI.
-   *
-   * @return string|bool
-   *   The site schema type URI if set, FALSE if otherwise.
-   */
-  public function getSiteSchemaUri() {
-    return $this->siteSchemaUri;
-  }
-
-  /**
-   * Sets the site schema URI.
-   *
-   * @param string $uri
-   *   The site schema type URI.
-   */
-  public function setSiteSchemaUri($uri) {
-    $this->siteSchemaUri = $uri;
-  }
-}
diff --git a/core/modules/rdf/lib/Drupal/rdf/Plugin/Core/Entity/RdfMapping.php b/core/modules/rdf/lib/Drupal/rdf/Plugin/Core/Entity/RdfMapping.php
new file mode 100644
index 0000000..d853b38
--- /dev/null
+++ b/core/modules/rdf/lib/Drupal/rdf/Plugin/Core/Entity/RdfMapping.php
@@ -0,0 +1,190 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\rdf\Plugin\Core\Entity\RdfMapping.
+ */
+
+namespace Drupal\rdf\Plugin\Core\Entity;
+
+use Drupal\Core\Config\Entity\ConfigEntityBase;
+use Drupal\Core\Entity\Annotation\EntityType;
+use Drupal\Core\Annotation\Translation;
+
+/**
+ * Config entity for working with RDF mappings.
+ *
+ * @EntityType(
+ *   id = "rdf_mapping",
+ *   label = @Translation("RDF mapping"),
+ *   module = "rdf",
+ *   controllers = {
+ *     "storage" = "Drupal\Core\Config\Entity\ConfigStorageController"
+ *   },
+ *   config_prefix = "rdf.mapping",
+ *   entity_keys = {
+ *     "id" = "id",
+ *     "uuid" = "uuid"
+ *   }
+ * )
+ */
+class RdfMapping extends ConfigEntityBase {
+
+  /**
+   * Unique ID for the config entity.
+   *
+   * @var string
+   */
+  public $id;
+
+  /**
+   * Unique UUID for the config entity.
+   *
+   * @var string
+   */
+  public $uuid;
+
+  /**
+   * Entity type to be mapped.
+   *
+   * @var string
+   */
+  public $targetEntityType;
+
+  /**
+   * Bundle to be mapped.
+   *
+   * @var string
+   */
+  public $bundle;
+
+  /**
+   * The RDF type mapping for this bundle.
+   *
+   * @var array
+   */
+  protected $types;
+
+  /**
+   * The mappings for fields on this bundle.
+   *
+   * @var array
+   */
+  protected $fieldMappings;
+
+  /**
+   * Gets the mapping for the bundle-level data.
+   *
+   * @return array|null
+   *   The field mapping, or NULL if there is no mapping.
+   */
+  public function getBundleMapping() {
+    $types = array();
+    if (isset($this->types)) {
+      $types = $this->types;
+    }
+    return array(
+      'types' => $types,
+    );
+  }
+
+  /**
+   * Sets the mapping for a bundle.
+   *
+   * This only sets bundle-level mappings, such as the RDF type. Mappings for
+   * a bundle's fields should be handled with setFieldMapping.
+   *
+   * Example usage:
+   * -Map the 'article' bundle to 'sioc:Post'.
+   * @code
+   * rdf_get_mapping('node', 'article')
+   *   ->setBundleMapping(array(
+   *     'types' => array('sioc:Post'),
+   *   ))
+   *   ->save();
+   * @endcode
+   *
+   * @param array $mapping
+   *   The bundle mapping.
+   *
+   * @return \Drupal\rdf\Plugin\Core\Entity\RdfMapping
+   *   The RdfMapping object.
+   */
+  public function setBundleMapping(array $mapping) {
+    if (isset($mapping['types'])) {
+      $this->types = $mapping['types'];
+    }
+
+    return $this;
+  }
+
+  /**
+   * Gets the mapping for a field on the bundle.
+   *
+   * @param string $field_name
+   *   The name of the field.
+   *
+   * @return array|null
+   *   The field mapping, or NULL if there is no mapping.
+   */
+  public function getFieldMapping($field_name) {
+    if (isset($this->fieldMappings[$field_name])) {
+      return $this->fieldMappings[$field_name];
+    }
+    return array();
+  }
+
+  /**
+   * Sets the mapping for a field.
+   *
+   * @param string $field_name
+   *   The name of the field.
+   * @param array $mapping
+   *   The field mapping.
+   *
+   * @return \Drupal\rdf\Plugin\Core\Entity\RdfMapping
+   *   The RdfMapping object.
+   */
+  public function setFieldMapping($field_name, array $mapping = array()) {
+    $this->fieldMappings[$field_name] = $mapping;
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function id() {
+    return $this->targetEntityType . '.' . $this->bundle;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function save() {
+    // Build an ID if none is set.
+    if (empty($this->id)) {
+      $this->id = $this->id();
+    }
+    return parent::save();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getExportProperties() {
+    $names = array(
+      'id',
+      'uuid',
+      'targetEntityType',
+      'bundle',
+      'types',
+      'fieldMappings'
+    );
+    $properties = array();
+    foreach ($names as $name) {
+      $properties[$name] = $this->get($name);
+    }
+    return $properties;
+  }
+
+}
\ No newline at end of file
diff --git a/core/modules/rdf/lib/Drupal/rdf/RdfConstants.php b/core/modules/rdf/lib/Drupal/rdf/RdfConstants.php
deleted file mode 100644
index b64ae91..0000000
--- a/core/modules/rdf/lib/Drupal/rdf/RdfConstants.php
+++ /dev/null
@@ -1,26 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains RdfConstants.
- */
-
-namespace Drupal\rdf;
-
-/**
- * Defines constants for RDF terms.
- */
-abstract class RdfConstants {
-  const RDF_TYPE            = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type';
-  // RDF Schema terms.
-  const RDFS_CLASS          = 'http://www.w3.org/2000/01/rdf-schema#class';
-  const RDFS_DOMAIN         = 'http://www.w3.org/2000/01/rdf-schema#domain';
-  const RDFS_IS_DEFINED_BY  = 'http://www.w3.org/2000/01/rdf-schema#isDefinedBy';
-  const RDFS_RANGE          = 'http://www.w3.org/2000/01/rdf-schema#range';
-  const RDFS_SUB_CLASS_OF   = 'http://www.w3.org/2000/01/rdf-schema#subClassOf';
-  // XSD datatypes.
-  const XSD_INTEGER         = 'http://www.w3.org/2001/XMLSchema#integer';
-  const XSD_DOUBLE          = 'http://www.w3.org/2001/XMLSchema#double';
-  const XSD_BOOLEAN         = 'http://www.w3.org/2001/XMLSchema#boolean';
-  const XSD_STRING          = 'http://www.w3.org/2001/XMLSchema#string';
-}
diff --git a/core/modules/rdf/lib/Drupal/rdf/RdfMappingEvents.php b/core/modules/rdf/lib/Drupal/rdf/RdfMappingEvents.php
deleted file mode 100644
index 0e3fdae..0000000
--- a/core/modules/rdf/lib/Drupal/rdf/RdfMappingEvents.php
+++ /dev/null
@@ -1,29 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains RdfMappingEvents.
- */
-
-namespace Drupal\rdf;
-
-/**
- * Contains all events for mapping site schemas to external vocabularies.
- */
-final class RdfMappingEvents {
-
-  /**
-   * Maps an array of incoming type URIs to a site schema URI.
-   *
-   * Modules can use this event to convert an RDF type from an externally
-   * defined vocabulary to a URI defined in the site's schema. From the site
-   * schema URI, the site can derive the Typed Data API ids, which can be used
-   * to create an entity.
-   *
-   * @see \Drupal\rdf\RdfMappingManager
-   *
-   * @var string
-   */
-  const MAP_TYPES_FROM_INPUT = 'rdf.map_types_from_input';
-
-}
diff --git a/core/modules/rdf/lib/Drupal/rdf/RdfMappingException.php b/core/modules/rdf/lib/Drupal/rdf/RdfMappingException.php
deleted file mode 100644
index d96722f..0000000
--- a/core/modules/rdf/lib/Drupal/rdf/RdfMappingException.php
+++ /dev/null
@@ -1,13 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains RdfMappingException.
- */
-
-namespace Drupal\rdf;
-
-/**
- * Exception to use when no RDF mapping is found.
- */
-class RdfMappingException extends \Exception { }
diff --git a/core/modules/rdf/lib/Drupal/rdf/RdfMappingManager.php b/core/modules/rdf/lib/Drupal/rdf/RdfMappingManager.php
deleted file mode 100644
index 90588e9..0000000
--- a/core/modules/rdf/lib/Drupal/rdf/RdfMappingManager.php
+++ /dev/null
@@ -1,101 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains RdfMappingManager.
- */
-
-namespace Drupal\rdf;
-
-use ReflectionClass;
-use Drupal\Core\Cache\CacheBackendInterface;
-use Drupal\rdf\MapTypesFromInputEvent;
-use Drupal\rdf\RdfMappingEvents;
-use Drupal\rdf\SiteSchema\BundleSchema;
-use Drupal\rdf\SiteSchema\SiteSchema;
-use Drupal\rdf\SiteSchema\SiteSchemaManager;
-use Symfony\Component\EventDispatcher\EventDispatcherInterface;
-
-/**
- * Manager for mapping internal and external schema terms.
- */
-class RdfMappingManager {
-
-  /**
-   * The event dispatcher.
-   *
-   * @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
-   */
-  protected $dispatcher;
-
-  /**
-   * The site schema manager.
-   *
-   * @var \Drupal\rdf\SiteSchema\SiteSchemaManager
-   */
-  protected $siteSchemaManager;
-
-  /**
-   * Constructor.
-   *
-   * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $dispatcher
-   *   The event dispatcher.
-   * @param \Drupal\rdf\SiteSchema\SiteSchemaManager $site_schema_manager
-   *   The site schema manager.
-   */
-  public function __construct(EventDispatcherInterface $dispatcher, SiteSchemaManager $site_schema_manager) {
-    $this->dispatcher = $dispatcher;
-    $this->siteSchemaManager = $site_schema_manager;
-  }
-
-  /**
-   * Convert an array of RDF type URIs to the corresponding TypedData IDs.
-   *
-   * @param array $input_rdf_types
-   *   An array of URIs for the type.
-   *
-   * @return array
-   *   An array containing entity_type and bundle.
-   *
-   * @throws \Drupal\rdf\RdfMappingException
-   */
-  public function getTypedDataIdsFromTypeUris($input_rdf_types) {
-    // Get the cache of site schema types.
-    $site_schema_types = $this->siteSchemaManager->getTypes();
-    // Map the RDF type from the incoming data to an RDF type defined in the
-    // internal site schema.
-    $type_uri = $this->mapTypesFromInput($input_rdf_types);
-    // If no site schema URI has been determined, then it's impossible to know
-    // what entity type to create. Throw an exception.
-    if ($type_uri == FALSE) {
-      throw new RdfMappingException(sprintf('No mapping to a site schema type URI found for incoming types (%s).', implode(',', $input_rdf_types)));
-    }
-    // Use the mapped RDF type URI to get the TypedData API ids the rest of the
-    // system uses (entity type and bundle).
-    return $site_schema_types[$type_uri];
-  }
-
-  /**
-   * Map an array of incoming URIs to an internal site schema URI.
-   *
-   * @param array $input_rdf_types
-   *   An array of RDF type URIs.
-   *
-   * @return string
-   *   The corresponding site schema type URI.
-   */
-  protected function mapTypesFromInput($input_rdf_types) {
-    // Create the event using the array of incoming RDF type URIs and the cache
-    // of internal site schema URIs.
-    $site_schema_types = $this->siteSchemaManager->getTypes();
-    $mapping_event = new MapTypesFromInputEvent($input_rdf_types, $site_schema_types);
-
-    // Allow other modules to map the incoming type URIs to an internal site
-    // schema type URI. For example, a content deployment module could take
-    // URIs from the staging site's schema and map them to the corresponding
-    // URI in the live site's schema.
-    $this->dispatcher->dispatch(RdfMappingEvents::MAP_TYPES_FROM_INPUT, $mapping_event);
-
-    return $mapping_event->getSiteSchemaUri();
-  }
-}
diff --git a/core/modules/rdf/lib/Drupal/rdf/SiteSchema/BundleSchema.php b/core/modules/rdf/lib/Drupal/rdf/SiteSchema/BundleSchema.php
deleted file mode 100644
index a20440a..0000000
--- a/core/modules/rdf/lib/Drupal/rdf/SiteSchema/BundleSchema.php
+++ /dev/null
@@ -1,64 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains BundleSchema.
- */
-
-namespace Drupal\rdf\SiteSchema;
-
-use Drupal\rdf\RdfConstants;
-use Drupal\rdf\SiteSchema\EntitySchema;
-
-/**
- * Defines RDF terms corresponding to Drupal bundles.
- */
-class BundleSchema extends EntitySchema {
-
-  /**
-   * The URI pattern for bundle site schema terms.
-   *
-   * @var string
-   */
-  public static $uriPattern = '{entity_type}/{bundle}';
-
-  /**
-   * The bundle that this term identifies.
-   *
-   * @var string
-   */
-  protected $bundle;
-
-  /**
-   * Constructor.
-   *
-   * @param \Drupal\rdf\SiteSchema\SiteSchema $site_schema
-   *   The schema the term is defined in.
-   * @param string $entity_type
-   *   The entity type.
-   * @param string $bundle
-   *   The bundle.
-   */
-  public function __construct($site_schema, $entity_type, $bundle) {
-    parent::__construct($site_schema, $entity_type);
-    $this->bundle = $bundle;
-  }
-
-  /**
-   * Implements \Drupal\rdf\SiteSchema\SchemaTermInterface::getUri().
-   */
-  public function getUri() {
-    $path = str_replace(array('{entity_type}', '{bundle}'), array($this->entityType, $this->bundle), static::$uriPattern);
-    return $this->siteSchema->getUri() . '/' . $path;
-  }
-
-  /**
-   * Overrides \Drupal\rdf\SiteSchema\SchemaTermBase::getProperties().
-   */
-  public function getProperties() {
-    $properties = parent::getProperties();
-    $properties[RdfConstants::RDFS_SUB_CLASS_OF] = $this->siteSchema->entity($this->entityType)->getUri();
-    return $properties;
-  }
-
-}
diff --git a/core/modules/rdf/lib/Drupal/rdf/SiteSchema/EntitySchema.php b/core/modules/rdf/lib/Drupal/rdf/SiteSchema/EntitySchema.php
deleted file mode 100644
index 282c904..0000000
--- a/core/modules/rdf/lib/Drupal/rdf/SiteSchema/EntitySchema.php
+++ /dev/null
@@ -1,73 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains EntitySchema.
- */
-
-namespace Drupal\rdf\SiteSchema;
-
-use Drupal\rdf\RdfConstants;
-use Drupal\rdf\SiteSchema\SchemaTermBase;
-
-/**
- * Defines RDF terms corresponding to Drupal entity types.
- */
-class EntitySchema extends SchemaTermBase {
-
-  /**
-   * The URI pattern for entity site schema terms.
-   *
-   * @var string
-   */
-  public static $uriPattern = '{entity_type}';
-
-  /**
-   * The entity type that this term identifies.
-   *
-   * @var string
-   */
-  protected $entityType;
-
-  /**
-   * Constructor.
-   *
-   * @param \Drupal\rdf\SiteSchema\SiteSchema $site_schema
-   *   The schema the term is defined in.
-   * @param string $entity_type
-   *   The entity type.
-   */
-  public function __construct($site_schema, $entity_type) {
-    parent::__construct($site_schema);
-    $this->entityType = $entity_type;
-  }
-
-  /**
-   * Implements \Drupal\rdf\SiteSchema\SchemaTermInterface::getGraph().
-   *
-   * @todo Loop through all fields and add their RDF descriptions.
-   */
-  public function getGraph() {
-    $graph = array();
-    $graph[$this->getUri()] = $this->getProperties();
-    return $graph;
-  }
-
-  /**
-   * Implements \Drupal\rdf\SiteSchema\SchemaTermInterface::getUri().
-   */
-  public function getUri() {
-    $path = str_replace('{entity_type}', $this->entityType , static::$uriPattern);
-    return $this->siteSchema->getUri() . '/' . $path;
-  }
-
-  /**
-   * Overrides \Drupal\rdf\SiteSchema\SchemaTermBase::getProperties().
-   */
-  public function getProperties() {
-    $properties = parent::getProperties();
-    $properties[RdfConstants::RDF_TYPE] = RdfConstants::RDFS_CLASS;
-    return $properties;
-  }
-
-}
diff --git a/core/modules/rdf/lib/Drupal/rdf/SiteSchema/SchemaTermBase.php b/core/modules/rdf/lib/Drupal/rdf/SiteSchema/SchemaTermBase.php
deleted file mode 100644
index d7afd1c..0000000
--- a/core/modules/rdf/lib/Drupal/rdf/SiteSchema/SchemaTermBase.php
+++ /dev/null
@@ -1,50 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains SchemaTermBase.
- */
-
-namespace Drupal\rdf\SiteSchema;
-
-use Drupal\rdf\RdfConstants;
-
-/**
- * Base class to define an RDF term in a schema.
- */
-abstract class SchemaTermBase implements SchemaTermInterface {
-
-  /**
-   * The URI pattern for this type of site schema term.
-   *
-   * @var string
-   */
-  public static $uriPattern;
-
-  /**
-   * The schema in which this term is defined.
-   *
-   * @var \Drupal\rdf\SiteSchema\SiteSchema
-   */
-  protected $siteSchema;
-
-  /**
-   * Constructor.
-   *
-   * @param \Drupal\rdf\SiteSchema\SiteSchema $site_schema
-   *   The namespace.
-   */
-  public function __construct($site_schema) {
-    $this->siteSchema = $site_schema;
-  }
-
-  /**
-   * Implements \Drupal\rdf\SiteSchema\SchemaTermInterface::getProperties().
-   */
-  public function getProperties() {
-    return array(
-      RdfConstants::RDFS_IS_DEFINED_BY => $this->siteSchema->getUri(),
-    );
-  }
-
-}
diff --git a/core/modules/rdf/lib/Drupal/rdf/SiteSchema/SchemaTermInterface.php b/core/modules/rdf/lib/Drupal/rdf/SiteSchema/SchemaTermInterface.php
deleted file mode 100644
index 342b51e..0000000
--- a/core/modules/rdf/lib/Drupal/rdf/SiteSchema/SchemaTermInterface.php
+++ /dev/null
@@ -1,44 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains SchemaTermInterface.
- */
-
-namespace Drupal\rdf\SiteSchema;
-
-interface SchemaTermInterface {
-
-  /**
-   * Get the full graph of terms and properties to display.
-   *
-   * When an RDF term URI is dereferenced, it usually contains a description of
-   * the term in RDF. To make it easier to use this description, include
-   * information about all related terms. For example, when viewing the RDF
-   * description for the RDF class which corresponds to a Drupal bundle, data
-   * about its fields would also be included.
-   *
-   * @return array
-   *   An array of terms and their properties, keyed by term URI.
-   */
-  public function getGraph();
-
-  /**
-   * Get the term properties.
-   *
-   * @return array
-   *   An array of properties for this term, keyed by URI.
-   */
-  public function getProperties();
-
-  /**
-   * Get the URI of the term.
-   *
-   * Implementations of this method will use the URI patterns defined in
-   * $uriPattern static variables and replace placeholders with actual values.
-   *
-   * @return string
-   *   The URI of the term.
-   */
-  public function getUri();
-}
diff --git a/core/modules/rdf/lib/Drupal/rdf/SiteSchema/SiteSchema.php b/core/modules/rdf/lib/Drupal/rdf/SiteSchema/SiteSchema.php
deleted file mode 100644
index e3153d1..0000000
--- a/core/modules/rdf/lib/Drupal/rdf/SiteSchema/SiteSchema.php
+++ /dev/null
@@ -1,90 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains SiteSchema.
- */
-
-namespace Drupal\rdf\SiteSchema;
-
-use Drupal\rdf\SiteSchema\BundleSchema;
-use Drupal\rdf\SiteSchema\EntitySchema;
-
-/**
- * Defines a site-generated schema.
- */
-class SiteSchema {
-
-  // Site schema paths. There are only two site schemas provided by core, which
-  // are not intended to be extensible. If a site wants to use external
-  // vocabulary terms, the appropriate way to do this is to use the RDF mapping
-  // system.
-  const CONTENT_DEPLOYMENT = 'site-schema/content-deployment/';
-  const SYNDICATION     = 'site-schema/syndication/';
-
-  /**
-   * The relative base path of the instantiated schema.
-   *
-   * @var string
-   */
-  protected $schemaPath;
-
-  /**
-   * Constructor.
-   *
-   * @param string $schema_path
-   *   The schema path constant, used to determine which schema to instantiate.
-   *
-   * @throws \UnexpectedValueException
-   */
-  public function __construct($schema_path) {
-    $valid_paths = array(self::CONTENT_DEPLOYMENT, self::SYNDICATION);
-    if (!in_array($schema_path, $valid_paths)) {
-      throw new \UnexpectedValueException(sprintf('%s is not a valid site schema path. Schema path must be one of %s.'), $schema_path, implode(', ', $valid_paths));
-    }
-    $this->schemaPath = $schema_path;
-  }
-
-  /**
-   * Get an entity's term definition in this vocabulary.
-   */
-  public function entity($entity_type) {
-    return new EntitySchema($this, $entity_type);
-  }
-
-  /**
-   * Get a bundle's term definition in this vocabulary.
-   */
-  public function bundle($entity_type, $bundle) {
-    return new BundleSchema($this, $entity_type, $bundle);
-  }
-
-  /**
-   * Get the URI of the schema.
-   *
-   * @return string
-   *   The URI of the schema.
-   */
-  public function getUri() {
-    return url($this->schemaPath, array('absolute' => TRUE));
-  }
-
-  /**
-   * Get the relative base path of the schema.
-   */
-  public function getPath() {
-    return $this->schemaPath;
-  }
-
-  /**
-   * Get the routes for the types of terms defined in this schema.
-   *
-   * @return array
-   *   An array of route patterns, keyed by controller method name.
-   */
-  public function getRoutes() {
-    return array(
-      'bundle' => $this->schemaPath . BundleSchema::$uriPattern,
-    );
-  }
-}
diff --git a/core/modules/rdf/lib/Drupal/rdf/SiteSchema/SiteSchemaManager.php b/core/modules/rdf/lib/Drupal/rdf/SiteSchema/SiteSchemaManager.php
deleted file mode 100644
index e42b868..0000000
--- a/core/modules/rdf/lib/Drupal/rdf/SiteSchema/SiteSchemaManager.php
+++ /dev/null
@@ -1,91 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains SiteSchemaManager.
- */
-
-namespace Drupal\rdf\SiteSchema;
-
-use ReflectionClass;
-use Drupal\Core\Cache\CacheBackendInterface;
-use Drupal\rdf\SiteSchema\SiteSchema;
-use Drupal\rdf\SiteSchema\BundleSchema;
-
-class SiteSchemaManager {
-
-  /**
-   * @var \Drupal\Core\Cache\CacheBackendInterface;
-   */
-  protected $cache;
-
-  /**
-   * Constructor.
-   */
-  public function __construct(CacheBackendInterface $cache) {
-    $this->cache = $cache;
-    $this->siteSchemas = array(
-      SiteSchema::CONTENT_DEPLOYMENT => new SiteSchema(SiteSchema::CONTENT_DEPLOYMENT),
-      SiteSchema::SYNDICATION => new SiteSchema(SiteSchema::SYNDICATION),
-    );
-  }
-
-  /**
-   * Writes the cache of site schema types.
-   */
-  public function writeCache() {
-    $data = array();
-
-    // Type URIs correspond to bundles. Iterate through the bundles to get the
-    // URI and data for them.
-    $entity_info = entity_get_info();
-    foreach (entity_get_bundles() as $entity_type => $bundles) {
-      // Only content entities are supported currently.
-      // @todo Consider supporting config entities.
-      $entity_type_info = $entity_info[$entity_type];
-      $reflection = new ReflectionClass($entity_type_info['class']);
-      if ($reflection->implementsInterface('\Drupal\Core\Config\Entity\ConfigEntityInterface')) {
-        continue;
-      }
-      foreach ($bundles as $bundle => $bundle_info) {
-        // Get a type URI for the bundle in each of the defined schemas.
-        foreach ($this->siteSchemas as $schema) {
-          $bundle_uri = $schema->bundle($entity_type, $bundle)->getUri();
-          $data[$bundle_uri] = array(
-            'entity_type' => $entity_type,
-            'bundle' => $bundle,
-          );
-        }
-      }
-    }
-    // These URIs only change when entity info changes, so cache it permanently
-    // and only clear it when entity_info is cleared.
-    $this->cache->set('rdf:site_schema:types', $data, CacheBackendInterface::CACHE_PERMANENT, array('entity_info' => TRUE));
-  }
-
-  public function getSchemas() {
-    return $this->siteSchemas;
-  }
-
-  public function getSchema($schema_path) {
-    return $this->siteSchemas[$schema_path];
-  }
-
-  /**
-   * Get the array of site schema types.
-   *
-   * @return array
-   *   An array of typed data ids (entity_type and bundle) keyed by
-   *   corresponding site schema URI.
-   */
-  public function getTypes() {
-    $cid = 'rdf:site_schema:types';
-    $cache = $this->cache->get($cid);
-    if (!$cache) {
-      $this->writeCache();
-      $cache = $this->cache->get($cid);
-    }
-    return $cache->data;
-  }
-
-}
diff --git a/core/modules/rdf/lib/Drupal/rdf/Tests/CommentAttributesTest.php b/core/modules/rdf/lib/Drupal/rdf/Tests/CommentAttributesTest.php
index dbdba31..d4038fb 100644
--- a/core/modules/rdf/lib/Drupal/rdf/Tests/CommentAttributesTest.php
+++ b/core/modules/rdf/lib/Drupal/rdf/Tests/CommentAttributesTest.php
@@ -48,6 +48,59 @@ public function setUp() {
     // Prepares commonly used URIs.
     $this->base_uri = url('<front>', array('absolute' => TRUE));
     $this->node_uri = url('node/' . $this->node->nid, array('absolute' => TRUE));
+
+    // Set relation between node and comment.
+    $article_mapping = rdf_get_mapping('node', 'article');
+    $comment_count_mapping = array(
+      'properties' => array('sioc:num_replies'),
+      'datatype' => 'xsd:integer',
+    );
+    $article_mapping->setFieldMapping('comment_count', $comment_count_mapping)->save();
+
+    // Save user mapping.
+    $user_mapping = rdf_get_mapping('user', 'user');
+    $username_mapping = array(
+      'properties' => array('foaf:name'),
+    );
+    $user_mapping->setFieldMapping('name', $username_mapping)->save();
+    $user_mapping->setFieldMapping('homepage', array('properties' => array('foaf:page'), 'mapping_type' => 'rel'))->save();
+
+    // Save comment mapping.
+    $mapping = rdf_get_mapping('comment', 'comment_node_article');
+    $mapping->setBundleMapping(array('types' => array('sioc:Post', 'sioct:Comment')))->save();
+    $field_mappings = array(
+      'title' => array(
+        'properties' => array('dc:title'),
+      ),
+      'created' => array(
+        'properties' => array('dc:date', 'dc:created'),
+        'datatype' => 'xsd:dateTime',
+        'datatype_callback' => 'date_iso8601',
+      ),
+      'changed' => array(
+        'properties' => array('dc:modified'),
+        'datatype' => 'xsd:dateTime',
+        'datatype_callback' => 'date_iso8601',
+      ),
+      'comment_body' => array(
+        'properties' => array('content:encoded'),
+      ),
+      'pid' => array(
+        'properties' => array('sioc:reply_of'),
+        'mapping_type' => 'rel',
+      ),
+      'uid' => array(
+        'properties' => array('sioc:has_creator'),
+        'mapping_type' => 'rel',
+      ),
+      'name' => array(
+        'properties' => array('foaf:name'),
+      ),
+    );
+    // Iterate over shared field mappings and save.
+    foreach ($field_mappings as $field_name => $field_mapping) {
+      $mapping->setFieldMapping($field_name, $field_mapping)->save();
+    }
   }
 
   /**
@@ -235,7 +288,12 @@ function _testBasicCommentRdfaMarkup($graph, $comment, $account = array()) {
     else {
       // The author is expected to be a blank node.
       $author_uri = $graph->get($comment_uri, '<http://rdfs.org/sioc/ns#has_creator>');
-      $this->assertTrue($author_uri->isBnode(), 'Comment relation to author found in RDF output (sioc:has_creator).');
+      if (!is_object($author_uri)) {
+        $this->fail('Comment relation to author found in RDF output (sioc:has_creator).');
+      }
+      else {
+        $this->assertTrue($author_uri->isBnode(), 'Comment relation to author found in RDF output (sioc:has_creator).');
+      }
     }
 
     // Author name.
diff --git a/core/modules/rdf/lib/Drupal/rdf/Tests/CrudTest.php b/core/modules/rdf/lib/Drupal/rdf/Tests/CrudTest.php
index 3383f94..73b0129 100644
--- a/core/modules/rdf/lib/Drupal/rdf/Tests/CrudTest.php
+++ b/core/modules/rdf/lib/Drupal/rdf/Tests/CrudTest.php
@@ -7,19 +7,19 @@
 
 namespace Drupal\rdf\Tests;
 
-use Drupal\simpletest\WebTestBase;
+use Drupal\simpletest\DrupalUnitTestBase;
 
 /**
  * Tests the RDF mapping CRUD functions.
  */
-class CrudTest extends WebTestBase {
+class CrudTest extends DrupalUnitTestBase {
 
   /**
    * Modules to enable.
    *
    * @var array
    */
-  public static $modules = array('rdf', 'rdf_test');
+  public static $modules = array('entity_test', 'rdf', 'system');
 
   public static function getInfo() {
     return array(
@@ -29,57 +29,82 @@ public static function getInfo() {
     );
   }
 
+  public function setUp() {
+    parent::setUp();
+    $this->prefix = 'rdf.mapping';
+    $this->entity_type = $this->bundle = 'entity_test';
+  }
+
   /**
-   * Tests inserting, loading, updating, and deleting RDF mappings.
+   * Tests creation of RDF mapping.
    */
-  function testCRUD() {
-    // Verify loading of a default mapping.
-    $mapping = _rdf_mapping_load('test_entity', 'test_bundle');
-    $this->assertTrue(count($mapping), 'Default mapping was found.');
-
-    // Verify saving a mapping.
-    $mapping = array(
-      'type' => 'crud_test_entity',
-      'bundle' => 'crud_test_bundle',
-      'mapping' => array(
-        'rdftype' => array('sioc:Post'),
-        'title' => array(
-          'predicates' => array('dc:title'),
-        ),
-        'uid' => array(
-          'predicates' => array('sioc:has_creator', 'dc:creator'),
-          'type' => 'rel',
-        ),
-      ),
-    );
-    $this->assertTrue(rdf_mapping_save($mapping) === SAVED_NEW, 'Mapping was saved.');
+  function testMappingCreation() {
+    $mapping_config_name = "{$this->prefix}.{$this->entity_type}.{$this->bundle}";
 
-    // Read the raw record from the {rdf_mapping} table.
-    $result = db_query('SELECT * FROM {rdf_mapping} WHERE type = :type AND bundle = :bundle', array(':type' => $mapping['type'], ':bundle' => $mapping['bundle']));
-    $stored_mapping = $result->fetchAssoc();
-    $stored_mapping['mapping'] = unserialize($stored_mapping['mapping']);
-    $this->assertEqual($mapping, $stored_mapping, 'Mapping was stored properly in the {rdf_mapping} table.');
+    // Save bundle mapping config.
+    rdf_get_mapping($this->entity_type, $this->bundle)->save();
+    // Test that config file was saved.
+    $mapping_config = config_get_storage_names_with_prefix('rdf.mapping');
+    $this->assertTrue(in_array($mapping_config_name, $mapping_config), 'Rdf mapping config saved.');
+  }
 
-    // Verify loading of saved mapping.
-    $this->assertEqual($mapping['mapping'], _rdf_mapping_load($mapping['type'], $mapping['bundle']), 'Saved mapping loaded successfully.');
+  /**
+   * Test the handling of bundle mappings.
+   */
+  function testBundleMapping() {
+    // Test that the bundle mapping can be saved.
+    $types = array('sioc:Post', 'foaf:Document');
+    rdf_get_mapping($this->entity_type, $this->bundle)
+      ->setBundleMapping(array(
+        'types' => $types
+      ))
+      ->save();
+    $bundle_mapping = rdf_get_mapping($this->entity_type, $this->bundle)
+      ->getBundleMapping();
+    $this->assertEqual($types, $bundle_mapping['types'], 'Bundle mapping saved.');
 
-    // Verify updating of mapping.
-    $mapping['mapping']['title'] = array(
-      'predicates' => array('dc2:bar2'),
-    );
-    $this->assertTrue(rdf_mapping_save($mapping) === SAVED_UPDATED, 'Mapping was updated.');
+    // Test that the bundle mapping can be edited.
+    $types = array('schema:BlogPosting');
+    rdf_get_mapping($this->entity_type, $this->bundle)
+      ->setBundleMapping(array(
+        'types' => $types
+      ))
+      ->save();
+    $bundle_mapping = rdf_get_mapping($this->entity_type, $this->bundle)
+      ->getBundleMapping();
+    $this->assertEqual($types, $bundle_mapping['types'], 'Bundle mapping edited.');
+  }
 
-    // Read the raw record from the {rdf_mapping} table.
-    $result = db_query('SELECT * FROM {rdf_mapping} WHERE type = :type AND bundle = :bundle', array(':type' => $mapping['type'], ':bundle' => $mapping['bundle']));
-    $stored_mapping = $result->fetchAssoc();
-    $stored_mapping['mapping'] = unserialize($stored_mapping['mapping']);
-    $this->assertEqual($mapping, $stored_mapping, 'Updated mapping was stored properly in the {rdf_mapping} table.');
+  /**
+   * Test the handling of field mappings.
+   */
+  function testFieldMapping() {
+    $field_name = 'created';
 
-    // Verify loading of saved mapping.
-    $this->assertEqual($mapping['mapping'], _rdf_mapping_load($mapping['type'], $mapping['bundle']), 'Saved mapping loaded successfully.');
+    // Test that the field mapping can be saved.
+    $mapping = array(
+      'properties' => array('dc:created'),
+      'datatype' => 'xsd:dateTime',
+      'datatype_callback' => 'date_iso8601',
+    );
+    rdf_get_mapping($this->entity_type, $this->bundle)
+      ->setFieldMapping($field_name, $mapping)
+      ->save();
+    $field_mapping = rdf_get_mapping($this->entity_type, $this->bundle)
+      ->getFieldMapping($field_name);
+    $this->assertEqual($field_mapping, $mapping, 'Field mapping saved.');
 
-    // Verify deleting of mapping.
-    $this->assertTrue(rdf_mapping_delete($mapping['type'], $mapping['bundle']), 'Mapping was deleted.');
-    $this->assertFalse(_rdf_mapping_load($mapping['type'], $mapping['bundle']), 'Deleted mapping is no longer found in the database.');
+    // Test that the field mapping can be edited.
+    $mapping = array(
+      'properties' => array('dc:date'),
+      'datatype' => 'foo:bar',
+      'datatype_callback' => 'date_iso8601',
+    );
+    rdf_get_mapping($this->entity_type, $this->bundle)
+      ->setFieldMapping($field_name, $mapping)
+      ->save();
+    $field_mapping = rdf_get_mapping($this->entity_type, $this->bundle)
+      ->getFieldMapping($field_name);
+    $this->assertEqual($field_mapping, $mapping, 'Field mapping edited.');
   }
 }
diff --git a/core/modules/rdf/lib/Drupal/rdf/Tests/FileFieldAttributesTest.php b/core/modules/rdf/lib/Drupal/rdf/Tests/FileFieldAttributesTest.php
new file mode 100644
index 0000000..7b4b7a6
--- /dev/null
+++ b/core/modules/rdf/lib/Drupal/rdf/Tests/FileFieldAttributesTest.php
@@ -0,0 +1,100 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\rdf\Tests\FileFieldAttributesTest.
+ */
+
+namespace Drupal\rdf\Tests;
+
+use Drupal\Core\Language\Language;
+use Drupal\file\Tests\FileFieldTestBase;
+
+/**
+ * Tests RDFa markup generation for File fields.
+ */
+class FileFieldAttributesTest extends FileFieldTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('rdf', 'file');
+
+  public static function getInfo() {
+    return array(
+      'name' => 'RDFa markup for files',
+      'description' => 'Tests the RDFa markup of filefields.',
+      'group' => 'RDF',
+    );
+  }
+
+  public function setUp() {
+    parent::setUp();
+    $this->fieldName = strtolower($this->randomName());
+
+    $type_name = 'article';
+    $field_settings = array(
+      'display_field' => '1',
+      'display_default' => '1',
+    );
+    $instance_settings = array(
+      'description_field' => '1',
+    );
+    $widget_settings = array();
+    $this->createFileField($this->fieldName, $type_name, $field_settings, $instance_settings, $widget_settings);
+
+    // Set the teaser display to show this field.
+    entity_get_display('node', 'article', 'teaser')
+      ->setComponent($this->fieldName, array(
+        'type' => 'file_default',
+      ))
+      ->save();
+
+    // Set the RDF mapping for the new field.
+    $mapping = rdf_get_mapping('node', 'article');
+    $mapping->setFieldMapping($this->fieldName, array('properties' => array('rdfs:seeAlso'), 'mapping_type' => 'rel'))->save();
+
+    $test_file = $this->getTestFile('text');
+
+    // Create a new node with the uploaded file.
+    $nid = $this->uploadNodeFile($test_file, $this->fieldName, $type_name);
+
+    $this->node = node_load($nid, TRUE);
+    $this->file = file_load($this->node->{$this->fieldName}[Language::LANGCODE_NOT_SPECIFIED][0]['fid']);
+
+  }
+
+  /**
+   * Tests if file fields in teasers have correct resources.
+   *
+   * Ensure that file fields have the correct resource as the object in RDFa
+   * when displayed as a teaser.
+   */
+  function testNodeTeaser() {
+    $node = $this->node;
+    $node_file = $this->file;
+
+    // Render the teaser.
+    $node_render_array = entity_view_multiple(array($node), 'teaser');
+    $html = drupal_render($node_render_array);
+
+    // Parses front page where the node is displayed in its teaser form.
+    $parser = new \EasyRdf_Parser_Rdfa();
+    $graph = new \EasyRdf_Graph();
+    $base_uri = url('<front>', array('absolute' => TRUE));
+    $parser->parse($graph, $html, 'rdfa', $base_uri);
+
+    $node_uri = url('node/' . $node->nid, array('absolute' => TRUE));
+    $file_uri = file_create_url($node_file->uri);
+
+    // Node relation to attached file.
+    $expected_value = array(
+      'type' => 'uri',
+      'value' => $file_uri,
+    );
+    $this->assertTrue($graph->hasProperty($node_uri, 'http://www.w3.org/2000/01/rdf-schema#seeAlso', $expected_value), 'Node to file relation found in RDF output (rdfs:seeAlso).');
+    $this->drupalGet('node');
+  }
+}
diff --git a/core/modules/rdf/lib/Drupal/rdf/Tests/GetNamespacesTest.php b/core/modules/rdf/lib/Drupal/rdf/Tests/GetNamespacesTest.php
index a133230..0457ee4 100644
--- a/core/modules/rdf/lib/Drupal/rdf/Tests/GetNamespacesTest.php
+++ b/core/modules/rdf/lib/Drupal/rdf/Tests/GetNamespacesTest.php
@@ -19,7 +19,7 @@ class GetNamespacesTest extends WebTestBase {
    *
    * @var array
    */
-  public static $modules = array('rdf', 'rdf_test');
+  public static $modules = array('rdf', 'rdf_test_namespaces');
 
   public static function getInfo() {
     return array(
diff --git a/core/modules/rdf/lib/Drupal/rdf/Tests/GetRdfNamespacesTest.php b/core/modules/rdf/lib/Drupal/rdf/Tests/GetRdfNamespacesTest.php
index 362a416..b2e881c 100644
--- a/core/modules/rdf/lib/Drupal/rdf/Tests/GetRdfNamespacesTest.php
+++ b/core/modules/rdf/lib/Drupal/rdf/Tests/GetRdfNamespacesTest.php
@@ -19,7 +19,7 @@ class GetRdfNamespacesTest extends WebTestBase {
    *
    * @var array
    */
-  public static $modules = array('rdf', 'rdf_test');
+  public static $modules = array('rdf', 'rdf_test_namespaces');
 
   public static function getInfo() {
     return array(
diff --git a/core/modules/rdf/lib/Drupal/rdf/Tests/ImageFieldAttributesTest.php b/core/modules/rdf/lib/Drupal/rdf/Tests/ImageFieldAttributesTest.php
new file mode 100644
index 0000000..360e853
--- /dev/null
+++ b/core/modules/rdf/lib/Drupal/rdf/Tests/ImageFieldAttributesTest.php
@@ -0,0 +1,104 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\rdf\Tests\ImageFieldAttributesTest.
+ */
+
+namespace Drupal\rdf\Tests;
+
+use Drupal\Core\Language\Language;
+use Drupal\image\Tests\ImageFieldTestBase;
+use Drupal\rdf\Tests\RdfTestHelper;
+
+/**
+ * Tests RDFa markup generation for image fields.
+ */
+class ImageFieldAttributesTest extends ImageFieldTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('rdf', 'image');
+
+  public static function getInfo() {
+    return array(
+      'name' => 'RDFa markup for imagefield',
+      'description' => 'Tests the RDFa markup of imagefields.',
+      'group' => 'RDF',
+    );
+  }
+
+  public function setUp() {
+    parent::setUp();
+
+    $this->fieldName = 'field_image';
+
+    // Create the image field.
+    $this->createImageField($this->fieldName, 'article');
+
+    // Set the RDF mapping for the new field.
+    rdf_get_mapping('node', 'article')
+      ->setFieldMapping($this->fieldName, array(
+        'properties' => array('og:image'),
+        'mapping_type' => 'rel',
+      ))
+      ->save();
+
+    // Get the test image that simpletest provides.
+    $image = current($this->drupalGetTestFiles('image'));
+
+    // Save a node with the image.
+    $nid = $this->uploadNodeImage($image, $this->fieldName, 'article');
+    $this->node = node_load($nid);
+    $this->file = file_load($this->node->{$this->fieldName}[Language::LANGCODE_NOT_SPECIFIED][0]['fid']);
+  }
+
+  /**
+   * Tests that image fields in teasers have correct resources.
+   */
+  function testNodeTeaser() {
+    $node = $this->node;
+    $node_file = $this->file;
+
+    // Set the display options for the teaser.
+    $display_options = array(
+      'type' => 'image',
+      'settings' => array('image_style'=> 'medium', 'image_link' => 'content'),
+    );
+    $display = entity_get_display('node', 'article', 'teaser');
+    $display->setComponent($this->fieldName, $display_options)
+      ->save();
+
+    // Render the teaser.
+    $node_render_array = node_view($node, 'teaser');
+    $html = drupal_render($node_render_array);
+
+    // Parse the teaser.
+    $parser = new \EasyRdf_Parser_Rdfa();
+    $graph = new \EasyRdf_Graph();
+    $base_uri = url('<front>', array('absolute' => TRUE));
+    $parser->parse($graph, $html, 'rdfa', $base_uri);
+
+    // Construct the node and image URIs for testing.
+    $node_uri = url('node/' . $node->nid, array('absolute' => TRUE));
+    $image_uri = image_style_url('medium', $node_file->uri);
+
+    // Test relations from node to image.
+    $expected_value = array(
+      'type' => 'uri',
+      'value' => $image_uri,
+    );
+    $this->assertTrue($graph->hasProperty($node_uri, 'http://ogp.me/ns#image', $expected_value), 'Node to file relation found in RDF output (og:image).');
+
+    // Test image type.
+    $expected_value = array(
+      'type' => 'uri',
+      'value' => 'http://xmlns.com/foaf/0.1/Image',
+    );
+    $this->assertTrue($graph->hasProperty($image_uri, 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type', $expected_value), 'Image type found in RDF output (foaf:Image).');
+  }
+
+}
diff --git a/core/modules/rdf/lib/Drupal/rdf/Tests/MappingDefinitionTest.php b/core/modules/rdf/lib/Drupal/rdf/Tests/MappingDefinitionTest.php
deleted file mode 100644
index ef33e6f..0000000
--- a/core/modules/rdf/lib/Drupal/rdf/Tests/MappingDefinitionTest.php
+++ /dev/null
@@ -1,135 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains Drupal\rdf\Tests\MappingDefinitionTest.
- */
-
-namespace Drupal\rdf\Tests;
-
-use Drupal\node\Tests\NodeTestBase;
-
-/**
- * Tests the RDF mapping definition functionality.
- */
-class MappingDefinitionTest extends NodeTestBase {
-
-  /**
-   * Modules to enable.
-   *
-   * @var array
-   */
-  public static $modules = array('rdf', 'rdf_test');
-
-  public static function getInfo() {
-    return array(
-      'name' => 'RDF mapping definition functionality',
-      'description' => 'Tests that RDF definitions are properly attached to entities.',
-      'group' => 'RDF',
-    );
-  }
-
-  function setUp() {
-    parent::setUp();
-    // NodeTestBase creates page content type for us.
-    // Defines RDF mapping for page content type.
-    $page_rdf_mapping = array(
-      'type' => 'node',
-      'bundle' => 'page',
-      'mapping' => array(
-        'rdftype' => array('foaf:DocumentBar'),
-        'body' => array(
-          'predicates' => array('dc:dummy-property'),
-        ),
-        'created' => array(
-          'predicates' => array('dc:dummy-date'),
-          'callback' => 'date_iso8601_foo',
-          'datatype' => 'xsd:dateTimeFoo',
-        ),
-      ),
-    );
-    rdf_mapping_save($page_rdf_mapping);
-  }
-
-  /**
-   * Creates a node of type page and tests whether the RDF mapping is
-   * attached to the node.
-   */
-  function testMappingDefinitionPage() {
-    $node = $this->drupalCreateNode(array('type' => 'page'));
-
-    $expected_mapping = array(
-      'rdftype' => array('foaf:DocumentBar'),
-      'title' => array(
-        'predicates' => array('dc:title'),
-      ),
-      'body' => array(
-        'predicates' => array('dc:dummy-property'),
-      ),
-      'created' => array(
-        'predicates' => array('dc:dummy-date'),
-        'callback' => 'date_iso8601_foo',
-        'datatype' => 'xsd:dateTimeFoo',
-      ),
-    );
-    $node = node_load($node->nid);
-    foreach ($expected_mapping as $key => $mapping) {
-      $this->assertEqual($node->rdf_mapping[$key], $mapping, format_string('Expected mapping found for @key.', array('@key' => $key)));
-    }
-  }
-
-  /**
-   * Creates a content type and a node of type test_bundle_hook_install and
-   * tests whether the RDF mapping defined in rdf_test.install is used.
-   */
-  function testMappingDefinitionTestBundleInstall() {
-    $this->drupalCreateContentType(array('type' => 'test_bundle_hook_install'));
-    $node = $this->drupalCreateNode(array('type' => 'test_bundle_hook_install'));
-
-    $expected_mapping = array(
-      'rdftype' => array('foo:mapping_install1', 'bar:mapping_install2'),
-      'title' => array(
-        'predicates' => array('dc:title'),
-      ),
-      'body' => array(
-        'predicates' => array('content:encoded'),
-      ),
-      'created' => array(
-        'predicates' => array('dc:date', 'dc:created'),
-        'callback' => 'date_iso8601',
-        'datatype' => 'xsd:dateTime',
-      ),
-    );
-    $node = node_load($node->nid);
-    foreach ($expected_mapping as $key => $mapping) {
-      $this->assertEqual($node->rdf_mapping[$key], $mapping, format_string('Expected mapping found for @key.', array('@key' => $key)));
-    }
-  }
-
-  /**
-   * Creates a random content type and node and ensures the default mapping for
-   * the node is being used.
-   */
-  function testMappingDefinitionRandomContentType() {
-    $type = $this->drupalCreateContentType();
-    $node = $this->drupalCreateNode(array('type' => $type->type));
-    $expected_mapping = array(
-      'rdftype' => array('sioc:Item', 'foaf:Document'),
-      'title' => array(
-        'predicates' => array('dc:title'),
-      ),
-      'body' => array(
-        'predicates' => array('content:encoded'),
-      ),
-      'created' => array(
-        'predicates' => array('dc:date', 'dc:created'),
-        'callback' => 'date_iso8601',
-        'datatype' => 'xsd:dateTime',
-      ),
-    );
-    $node = node_load($node->nid);
-    foreach ($expected_mapping as $key => $mapping) {
-      $this->assertEqual($node->rdf_mapping[$key], $mapping, format_string('Expected mapping found for @key.', array('@key' => $key)));
-    }
-  }
-}
diff --git a/core/modules/rdf/lib/Drupal/rdf/Tests/MappingHookTest.php b/core/modules/rdf/lib/Drupal/rdf/Tests/MappingHookTest.php
deleted file mode 100644
index eb1340e..0000000
--- a/core/modules/rdf/lib/Drupal/rdf/Tests/MappingHookTest.php
+++ /dev/null
@@ -1,50 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\rdf\Tests\MappingHookTest.
- */
-
-namespace Drupal\rdf\Tests;
-
-use Drupal\simpletest\WebTestBase;
-
-/**
- * Tests the RDF mapping hook.
- */
-class MappingHookTest extends WebTestBase {
-
-  /**
-   * Modules to enable.
-   *
-   * @var array
-   */
-  public static $modules = array('rdf', 'rdf_test', 'field_test');
-
-  public static function getInfo() {
-    return array(
-      'name' => 'RDF mapping hook',
-      'description' => 'Test hook_rdf_mapping().',
-      'group' => 'RDF',
-    );
-  }
-
-  /**
-   * Tests that hook_rdf_mapping() correctly returns and processes mapping.
-   */
-  function testMapping() {
-    // Test that the mapping is returned correctly by the hook.
-    $mapping = rdf_mapping_load('test_entity', 'test_bundle');
-    $this->assertIdentical($mapping['rdftype'], array('sioc:Post'), 'Mapping for rdftype is sioc:Post.');
-    $this->assertIdentical($mapping['title'], array('predicates' => array('dc:title')), 'Mapping for title is dc:title.');
-    $this->assertIdentical($mapping['created'], array(
-      'predicates' => array('dc:created'),
-      'datatype' => 'xsd:dateTime',
-      'callback' => 'date_iso8601',
-    ), 'Mapping for created is dc:created with datatype xsd:dateTime and callback date_iso8601.');
-    $this->assertIdentical($mapping['uid'], array('predicates' => array('sioc:has_creator', 'dc:creator'), 'type' => 'rel'), 'Mapping for uid is sioc:has_creator and dc:creator, and type is rel.');
-
-    $mapping = rdf_mapping_load('test_entity', 'test_bundle_no_mapping');
-    $this->assertEqual($mapping, array(), 'Empty array returned when an entity type, bundle pair has no mapping.');
-  }
-}
diff --git a/core/modules/rdf/lib/Drupal/rdf/Tests/NodeAttributesTest.php b/core/modules/rdf/lib/Drupal/rdf/Tests/NodeAttributesTest.php
index e8df665..6a0e267 100644
--- a/core/modules/rdf/lib/Drupal/rdf/Tests/NodeAttributesTest.php
+++ b/core/modules/rdf/lib/Drupal/rdf/Tests/NodeAttributesTest.php
@@ -29,6 +29,24 @@ public static function getInfo() {
     );
   }
 
+  public function setUp() {
+    parent::setUp();
+
+    rdf_get_mapping('node', 'article')
+      ->setBundleMapping(array(
+        'types' => array('sioc:Item', 'foaf:Document'),
+      ))
+      ->setFieldMapping('title', array(
+        'properties' => array('dc:title'),
+      ))
+      ->setFieldMapping('created', array(
+        'properties' => array('dc:date', 'dc:created'),
+        'datatype' => 'xsd:dateTime',
+        'datatype_callback' => 'date_iso8601',
+      ))
+      ->save();
+  }
+
   /**
    * Creates a node of type article and tests its RDFa markup.
    */
diff --git a/core/modules/rdf/lib/Drupal/rdf/Tests/RdfMappingEventTest.php b/core/modules/rdf/lib/Drupal/rdf/Tests/RdfMappingEventTest.php
deleted file mode 100644
index c099a9a..0000000
--- a/core/modules/rdf/lib/Drupal/rdf/Tests/RdfMappingEventTest.php
+++ /dev/null
@@ -1,63 +0,0 @@
-<?php
-/**
- * @file
- * Contains RdfMappingEventTest.
- */
-
-namespace Drupal\rdf\Tests;
-
-use Drupal\rdf\RdfMappingManager;
-use Drupal\rdf\EventSubscriber\MappingSubscriber;
-use Drupal\rdf_test_mapping\EventSubscriber\TestMappingSubscriber;
-use Drupal\rdf\SiteSchema\BundleSchema;
-use Drupal\rdf\SiteSchema\SiteSchema;
-use Drupal\rdf\SiteSchema\SiteSchemaManager;
-use Drupal\simpletest\WebTestBase;
-use Symfony\Component\EventDispatcher\EventDispatcher;
-
-/**
- * Test the RDF mapping events.
- *
- * This is implemented as a WebTest because it depends on entity info.
- */
-class RdfMappingEventTest extends WebTestBase {
-
-  /**
-   * Modules to enable.
-   *
-   * @var array
-   */
-  public static $modules = array('rdf', 'rdf_test_mapping', 'entity_test');
-
-  public static function getInfo() {
-    return array(
-      'name' => 'RDF mapping tests',
-      'description' => 'Tests the event-based RDF mapping system.',
-      'group' => 'RDF',
-    );
-  }
-
-  /**
-   * Test that other modules can define incoming type mappings.
-   */
-  public function testMapInputType() {
-    $dispatcher = new EventDispatcher();
-    $dispatcher->addSubscriber(new MappingSubscriber());
-    $dispatcher->addSubscriber(new TestMappingSubscriber());
-    $site_schema_manager = new SiteSchemaManager($this->container->get('cache.cache'));
-    $mapping_manager = new RdfMappingManager($dispatcher, $site_schema_manager);
-
-    // Test that a site schema URI is mapped to itself. This is the default
-    // behavior.
-    $schema = new SiteSchema(SiteSchema::CONTENT_DEPLOYMENT);
-    $bundle_schema = $schema->bundle('entity_test', 'entity_test');
-    $site_schema_type = $bundle_schema->getUri();
-    $typed_data_ids = $mapping_manager->getTypedDataIdsFromTypeUris(array($site_schema_type));
-    $this->assertTrue($typed_data_ids['bundle'] == 'entity_test', 'An internal site schema type URI is properly handled.');
-
-    // Test that a module can map an external URI to a site schema URI.
-    $typed_data_ids = $mapping_manager->getTypedDataIdsFromTypeUris(array(TestMappingSubscriber::STAGING_SITE_TYPE_URI));
-    $this->assertTrue($typed_data_ids['bundle'] == 'entity_test', 'Modules can map external type URIs to a site schema type.');
-  }
-
-}
diff --git a/core/modules/rdf/lib/Drupal/rdf/Tests/RdfaAttributesTest.php b/core/modules/rdf/lib/Drupal/rdf/Tests/RdfaAttributesTest.php
new file mode 100644
index 0000000..9881e9c
--- /dev/null
+++ b/core/modules/rdf/lib/Drupal/rdf/Tests/RdfaAttributesTest.php
@@ -0,0 +1,138 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\rdf\Tests\RdfaAttributesTest.
+ */
+
+namespace Drupal\rdf\Tests;
+
+use Drupal\simpletest\DrupalUnitTestBase;
+
+/**
+ * Tests RDFa attribute generation.
+ */
+class RdfaAttributesTest extends DrupalUnitTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('rdf');
+
+  public static function getInfo() {
+    return array(
+      'name' => 'RDFa attributes',
+      'description' => 'Test RDFa attribute generation from RDF mapping.',
+      'group' => 'RDF',
+    );
+  }
+
+  /**
+   * Test attribute creation for mappings which use 'property'.
+   */
+  function testProperty() {
+    $properties = array('dc:title');
+
+    $mapping = array(
+      'properties' => $properties,
+    );
+    $expected_attributes = array(
+      'property' => $properties,
+    );
+
+    $this->_testAttributes($expected_attributes, $mapping);
+  }
+
+  /**
+   * Test attribute creation for mappings which use 'datatype'.
+   */
+  function testDatatype() {
+    $properties = array('foo:bar1');
+    $datatype = 'foo:bar1type';
+
+    $mapping = array(
+      'datatype' => $datatype,
+      'properties' => $properties,
+    );
+    $expected_attributes = array(
+      'datatype' => $datatype,
+      'property' => $properties,
+    );
+
+    $this->_testAttributes($expected_attributes, $mapping);
+  }
+
+  /**
+   * Test attribute creation for mappings which override human-readable content.
+   */
+  function testDatatypeCallback() {
+    $properties = array('dc:created');
+    $datatype = 'xsd:dateTime';
+
+    $date = 1252750327;
+    $isoDate = date('c', $date);
+
+    $mapping = array(
+      'datatype' => $datatype,
+      'properties' => $properties,
+      'datatype_callback' => 'date_iso8601',
+    );
+    $expected_attributes = array(
+      'datatype' => $datatype,
+      'property' => $properties,
+      'content' => $isoDate,
+    );
+
+    $this->_testAttributes($expected_attributes, $mapping, $date);
+  }
+
+  /**
+   * Test attribute creation for mappings which use 'rel'.
+   */
+  function testRel() {
+    $properties = array('sioc:has_creator', 'dc:creator');
+
+    $mapping = array(
+      'properties' => $properties,
+      'mapping_type' => 'rel',
+    );
+    $expected_attributes = array(
+      'rel' => $properties,
+    );
+
+    $this->_testAttributes($expected_attributes, $mapping);
+  }
+
+  /**
+   * Helper function to test attribute generation.
+   *
+   * @param array $field_mapping
+   *   The field mapping to merge into the RDF mapping config.
+   * @param array $expected_attributes
+   *   The expected return of rdf_rdfa_attributes.
+   */
+  protected function _testAttributes($expected_attributes, $field_mapping, $data = NULL) {
+    $this->saveMapping($field_mapping);
+
+    $mapping = rdf_get_mapping('node', 'article')
+      ->getFieldMapping('field_test');
+    $attributes = rdf_rdfa_attributes($mapping, $data);
+    ksort($expected_attributes);
+    ksort($attributes);
+    $this->assertEqual($expected_attributes, $attributes);
+  }
+
+  /**
+   * Helper function to save mapping using config system.
+   *
+   * @param array $field_mapping
+   *   The field mapping.
+   */
+  protected function saveMapping($field_mapping) {
+    rdf_get_mapping('node', 'article')
+      ->setFieldMapping('field_test', $field_mapping)
+      ->save();
+  }
+}
diff --git a/core/modules/rdf/lib/Drupal/rdf/Tests/RdfaMarkupTest.php b/core/modules/rdf/lib/Drupal/rdf/Tests/RdfaMarkupTest.php
deleted file mode 100644
index bf47b46..0000000
--- a/core/modules/rdf/lib/Drupal/rdf/Tests/RdfaMarkupTest.php
+++ /dev/null
@@ -1,256 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\rdf\Tests\RdfaMarkupTest.
- */
-
-namespace Drupal\rdf\Tests;
-
-use Drupal\Core\Language\Language;
-use Drupal\simpletest\WebTestBase;
-
-/**
- * Tests RDFa markup generation.
- */
-class RdfaMarkupTest extends WebTestBase {
-
-  /**
-   * Modules to enable.
-   *
-   * @var array
-   */
-  public static $modules = array('rdf', 'field_test', 'rdf_test');
-
-  protected $profile = 'standard';
-
-  public static function getInfo() {
-    return array(
-      'name' => 'RDFa markup',
-      'description' => 'Test RDFa markup generation.',
-      'group' => 'RDF',
-    );
-  }
-
-  /**
-   * Tests rdf_rdfa_attributes().
-   */
-  function testDrupalRdfaAttributes() {
-    // Same value as the one in the HTML tag (no callback function).
-    $expected_attributes = array(
-      'property' => array('dc:title'),
-    );
-    $mapping = rdf_mapping_load('test_entity', 'test_bundle');
-    $attributes = rdf_rdfa_attributes($mapping['title']);
-    ksort($expected_attributes);
-    ksort($attributes);
-    $this->assertEqual($expected_attributes, $attributes);
-
-    // Value different from the one in the HTML tag (callback function).
-    $date = 1252750327;
-    $isoDate = date('c', $date);
-    $expected_attributes = array(
-      'datatype' => 'xsd:dateTime',
-      'property' => array('dc:created'),
-      'content' => $isoDate,
-    );
-    $mapping = rdf_mapping_load('test_entity', 'test_bundle');
-    $attributes = rdf_rdfa_attributes($mapping['created'], $date);
-    ksort($expected_attributes);
-    ksort($attributes);
-    $this->assertEqual($expected_attributes, $attributes);
-
-    // Same value as the one in the HTML tag with datatype.
-    $expected_attributes = array(
-      'datatype' => 'foo:bar1type',
-      'property' => array('foo:bar1'),
-    );
-    $mapping = rdf_mapping_load('test_entity', 'test_bundle');
-    $attributes = rdf_rdfa_attributes($mapping['foobar1']);
-    ksort($expected_attributes);
-    ksort($attributes);
-    $this->assertEqual($expected_attributes, $attributes);
-
-    // ObjectProperty mapping (rel).
-    $expected_attributes = array(
-      'rel' => array('sioc:has_creator', 'dc:creator'),
-    );
-    $mapping = rdf_mapping_load('test_entity', 'test_bundle');
-    $attributes = rdf_rdfa_attributes($mapping['foobar_objproperty1']);
-    ksort($expected_attributes);
-    ksort($attributes);
-    $this->assertEqual($expected_attributes, $attributes);
-
-    // Inverse ObjectProperty mapping (rev).
-    $expected_attributes = array(
-      'rev' => array('sioc:reply_of'),
-    );
-    $mapping = rdf_mapping_load('test_entity', 'test_bundle');
-    $attributes = rdf_rdfa_attributes($mapping['foobar_objproperty2']);
-    ksort($expected_attributes);
-    ksort($attributes);
-    $this->assertEqual($expected_attributes, $attributes);
-  }
-
-  /**
-   * Tests if file fields in teasers have correct resources.
-   *
-   * Ensure that file fields have the correct resource as the object in RDFa
-   * when displayed as a teaser.
-   */
-  function testAttributesInMarkupFile() {
-    // Create a user to post the image.
-    $admin_user = $this->drupalCreateUser(array('edit own article content', 'revert article revisions', 'administer content types'));
-    $this->drupalLogin($admin_user);
-
-    $langcode = Language::LANGCODE_NOT_SPECIFIED;
-    $bundle_name = "article";
-
-    $field_name = 'file_test';
-    $field = array(
-      'field_name' => $field_name,
-      'type' => 'file',
-    );
-    field_create_field($field);
-    $instance = array(
-      'field_name' => $field_name,
-      'entity_type' => 'node',
-      'bundle' => $bundle_name,
-    );
-    field_create_instance($instance);
-
-    entity_get_form_display('node', $bundle_name, 'default')
-      ->setComponent($field_name, array(
-        'type' => 'file_generic',
-      ))
-      ->save();
-    entity_get_display('node', $bundle_name, 'teaser')
-      ->setComponent($field_name, array(
-        'type' => 'file_default',
-      ))
-      ->save();
-
-    // Set the RDF mapping for the new field.
-    $rdf_mapping = rdf_mapping_load('node', $bundle_name);
-    $rdf_mapping += array($field_name => array('predicates' => array('rdfs:seeAlso'), 'type' => 'rel'));
-    $rdf_mapping_save = array('mapping' => $rdf_mapping, 'type' => 'node', 'bundle' => $bundle_name);
-    rdf_mapping_save($rdf_mapping_save);
-
-    // Get the test file that simpletest provides.
-    $file = current($this->drupalGetTestFiles('text'));
-
-    // Prepare image variables.
-    $image_field = "field_image";
-    // Get the test image that simpletest provides.
-    $image = current($this->drupalGetTestFiles('image'));
-
-    // Create an array for drupalPost with the field names as the keys and
-    // the URIs for the test files as the values.
-    $edit = array("files[" . $field_name . "_" . $langcode . "_0]" => drupal_realpath($file->uri),
-                  "files[" . $image_field . "_" . $langcode . "_0]" => drupal_realpath($image->uri));
-
-    // Create node and save, then edit node to upload files.
-    $node = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1));
-    $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
-
-    // Prepares filenames for lookup in RDF graph.
-    $node = node_load($node->nid);
-    $node_uri = url('node/' . $node->nid, array('absolute' => TRUE));
-    $file_uri = file_create_url(file_load($node->file_test['und'][0]['fid'])->uri);
-    $image_uri = image_style_url('medium', file_load($node->field_image['und'][0]['fid'])->uri);
-    $base_uri = url('<front>', array('absolute' => TRUE));
-
-    // Edits the node to add tags.
-    $tag1 = $this->randomName(8);
-    $tag2 = $this->randomName(8);
-    $edit = array();
-    $edit['field_tags[' . Language::LANGCODE_NOT_SPECIFIED . ']'] = "$tag1, $tag2";
-    $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
-    $term_1_id = key(taxonomy_term_load_multiple_by_name($tag1));
-    $taxonomy_term_1_uri = url('taxonomy/term/' . $term_1_id, array('absolute' => TRUE));
-    $term_2_id = key(taxonomy_term_load_multiple_by_name($tag2));
-    $taxonomy_term_2_uri = url('taxonomy/term/' . $term_2_id, array('absolute' => TRUE));
-
-    // Parses front page where the node is displayed in its teaser form.
-    $parser = new \EasyRdf_Parser_Rdfa();
-    $graph = new \EasyRdf_Graph();
-    $parser->parse($graph, $this->drupalGet('node'), 'rdfa', $base_uri);
-    $rdf_output = $graph->toArray();
-
-    // Inspects RDF graph output.
-    // Node relations to attached file.
-    $expected_value = array(
-      'type' => 'uri',
-      'value' => $file_uri,
-    );
-    $this->assertTrue($graph->hasProperty($node_uri, 'http://www.w3.org/2000/01/rdf-schema#seeAlso', $expected_value), 'Node to file relation found in RDF output (rdfs:seeAlso).');
-
-    // Node relations to attached image.
-    $expected_value = array(
-      'type' => 'uri',
-      'value' => $image_uri,
-    );
-    $this->assertTrue($graph->hasProperty($node_uri, 'http://www.w3.org/2000/01/rdf-schema#seeAlso', $expected_value), 'Node to file relation found in RDF output (rdfs:seeAlso).');
-    $expected_value = array(
-      'type' => 'uri',
-      'value' => $image_uri,
-    );
-    $this->assertTrue($graph->hasProperty($node_uri, 'http://ogp.me/ns#image', $expected_value), 'Node to file relation found in RDF output (og:image).');
-    // Image type.
-    $expected_value = array(
-      'type' => 'uri',
-      'value' => 'http://xmlns.com/foaf/0.1/Image',
-    );
-    $this->assertTrue($graph->hasProperty($image_uri, 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type', $expected_value), 'Image type found in RDF output (foaf:Image).');
-
-    // Node relations to taxonomy terms.
-    $expected_value = array(
-      'type' => 'uri',
-      'value' => $taxonomy_term_1_uri,
-    );
-    $this->assertTrue($graph->hasProperty($node_uri, 'http://purl.org/dc/terms/subject', $expected_value), 'Node to term relation found in RDF output (dc:subject).');
-    $expected_value = array(
-      'type' => 'uri',
-      'value' => $taxonomy_term_2_uri,
-    );
-    $this->assertTrue($graph->hasProperty($node_uri, 'http://purl.org/dc/terms/subject', $expected_value), 'Node to term relation found in RDF output (dc:subject).');
-
-    // Taxonomy terms triples.
-    // Term 1.
-    $expected_value = array(
-      'type' => 'uri',
-      'value' => 'http://www.w3.org/2004/02/skos/core#Concept',
-    );
-    $this->assertTrue($graph->hasProperty($taxonomy_term_1_uri, 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type', $expected_value), 'Taxonomy term type found in RDF output (skos:Concept).');
-    $expected_value = array(
-      'type' => 'literal',
-      'value' => $tag1,
-      'lang' => 'en',
-    );
-    $this->assertTrue($graph->hasProperty($taxonomy_term_1_uri, 'http://www.w3.org/2000/01/rdf-schema#label', $expected_value), 'Taxonomy term name found in RDF output (rdfs:label).');
-    $expected_value = array(
-      'type' => 'literal',
-      'value' => $tag1,
-      'lang' => 'en',
-    );
-    $this->assertTrue($graph->hasProperty($taxonomy_term_1_uri, 'http://www.w3.org/2004/02/skos/core#prefLabel', $expected_value), 'Taxonomy term name found in RDF output (skos:prefLabel).');
-    // Term 2.
-    $expected_value = array(
-      'type' => 'uri',
-      'value' => 'http://www.w3.org/2004/02/skos/core#Concept',
-    );
-    $this->assertTrue($graph->hasProperty($taxonomy_term_2_uri, 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type', $expected_value), 'Taxonomy term type found in RDF output (skos:Concept).');
-    $expected_value = array(
-      'type' => 'literal',
-      'value' => $tag2,
-      'lang' => 'en',
-    );
-    $this->assertTrue($graph->hasProperty($taxonomy_term_2_uri, 'http://www.w3.org/2000/01/rdf-schema#label', $expected_value), 'Taxonomy term name found in RDF output (rdfs:label).');
-    $expected_value = array(
-      'type' => 'literal',
-      'value' => $tag2,
-      'lang' => 'en',
-    );
-    $this->assertTrue($graph->hasProperty($taxonomy_term_2_uri, 'http://www.w3.org/2004/02/skos/core#prefLabel', $expected_value), 'Taxonomy term name found in RDF output (skos:prefLabel).');
-  }
-}
diff --git a/core/modules/rdf/lib/Drupal/rdf/Tests/SiteSchemaTest.php b/core/modules/rdf/lib/Drupal/rdf/Tests/SiteSchemaTest.php
deleted file mode 100644
index 986118b..0000000
--- a/core/modules/rdf/lib/Drupal/rdf/Tests/SiteSchemaTest.php
+++ /dev/null
@@ -1,54 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains SiteSchemaTest.
- */
-
-namespace Drupal\rdf\Tests;
-
-use Drupal\rdf\SiteSchema\BundleSchema;
-use Drupal\rdf\SiteSchema\SiteSchema;
-use Drupal\simpletest\WebTestBase;
-
-/**
- * Tests for RDF namespaces XML serialization.
- */
-class SiteSchemaTest extends WebTestBase {
-
-  /**
-   * Modules to enable.
-   *
-   * @var array
-   */
-  public static $modules = array('rdf', 'entity_test');
-
-  public static function getInfo() {
-    return array(
-      'name' => 'RDF site schema test',
-      'description' => 'Confirm that site-generated schemas are created for entity, bundle, field, and field property.',
-      'group' => 'RDF',
-    );
-  }
-
-  /**
-   * Tests site-generated schema.
-   */
-  function testSiteSchema() {
-    $entity_type = $bundle = 'entity_test';
-    $schema = new SiteSchema(SiteSchema::SYNDICATION);
-    $schema_path = 'site-schema/syndication/';
-
-    // Bundle.
-    $bundle_schema = $schema->bundle($entity_type, $bundle);
-    $bundle_uri = url("$schema_path$entity_type/$bundle", array('absolute' => TRUE));
-    $bundle_properties = array(
-      'http://www.w3.org/2000/01/rdf-schema#isDefinedBy' => url($schema_path, array('absolute' => TRUE)),
-      'http://www.w3.org/1999/02/22-rdf-syntax-ns#type' => 'http://www.w3.org/2000/01/rdf-schema#class',
-      'http://www.w3.org/2000/01/rdf-schema#subClassOf' => url("$schema_path$entity_type", array('absolute' => TRUE)),
-    );
-    $this->assertEqual($bundle_schema->getUri(), $bundle_uri, 'Bundle term URI is generated correctly.');
-    $this->assertEqual($bundle_schema->getProperties(), $bundle_properties, 'Bundle term properties are generated correctly.');
-  }
-
-}
diff --git a/core/modules/rdf/lib/Drupal/rdf/Tests/TaxonomyAttributesTest.php b/core/modules/rdf/lib/Drupal/rdf/Tests/TaxonomyAttributesTest.php
index 4b26a04..435583c 100644
--- a/core/modules/rdf/lib/Drupal/rdf/Tests/TaxonomyAttributesTest.php
+++ b/core/modules/rdf/lib/Drupal/rdf/Tests/TaxonomyAttributesTest.php
@@ -29,12 +29,27 @@ public static function getInfo() {
     );
   }
 
+  function setUp() {
+    parent::setUp();
+
+    $this->vocabulary = $this->createVocabulary();
+
+    // RDF mapping - term bundle.
+    rdf_get_mapping('taxonomy_term', $this->vocabulary->id())
+      ->setBundleMapping(array(
+        'types' => array('skos:Concept')
+      ))
+      ->setFieldMapping('name', array(
+        'properties' => array('rdfs:label', 'skos:prefLabel')
+      ))
+      ->save();
+  }
+
   /**
    * Creates a random term and ensures the RDF output is correct.
    */
   function testTaxonomyTermRdfaAttributes() {
-    $vocabulary = $this->createVocabulary();
-    $term = $this->createTerm($vocabulary);
+    $term = $this->createTerm($this->vocabulary);
     $term_uri = url('taxonomy/term/' . $term->id(), array('absolute' => TRUE));
 
     // Parses the term's page and checks that the RDF output is correct.
diff --git a/core/modules/rdf/lib/Drupal/rdf/Tests/TaxonomyTermFieldAttributesTest.php b/core/modules/rdf/lib/Drupal/rdf/Tests/TaxonomyTermFieldAttributesTest.php
new file mode 100644
index 0000000..75d23cc
--- /dev/null
+++ b/core/modules/rdf/lib/Drupal/rdf/Tests/TaxonomyTermFieldAttributesTest.php
@@ -0,0 +1,181 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\rdf\Tests\TaxonomyTermFieldAttributesTest.
+ */
+
+namespace Drupal\rdf\Tests;
+
+use Drupal\Core\Language\Language;
+use Drupal\rdf\Tests\RdfTestHelper;
+use Drupal\taxonomy\Tests\TaxonomyTestBase;
+
+/**
+ * Tests RDFa markup generation for taxonomy term fields.
+ */
+class TaxonomyTermFieldAttributesTest extends TaxonomyTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('rdf', 'field_test', 'file', 'image');
+
+  public static function getInfo() {
+    return array(
+      'name' => 'RDFa markup for taxonomy term fields',
+      'description' => 'Tests the RDFa markup of taxonomy term fields.',
+      'group' => 'RDF',
+    );
+  }
+
+  public function setUp() {
+    parent::setUp();
+
+    $this->web_user = $this->drupalCreateUser(array('bypass node access', 'administer taxonomy'));
+    $this->drupalLogin($this->web_user);
+    $this->vocabulary = $this->createVocabulary();
+
+    // Setup a field and instance.
+    $this->fieldName = 'field_taxonomy_test';
+
+    // Create the field.
+    $this->createTaxonomyTermReferenceField($this->fieldName, $this->vocabulary);
+
+    // Set the RDF mapping for the new field.
+    rdf_get_mapping('node', 'article')
+      ->setFieldMapping($this->fieldName, array(
+        'properties' => array('dc:subject'),
+        'mapping_type' => 'rel',
+      ))
+      ->save();
+
+    rdf_get_mapping('taxonomy_term', $this->vocabulary->id())
+      ->setBundleMapping(array(
+        'types' => array('skos:Concept')
+      ))
+      ->setFieldMapping('name', array(
+        'properties' => array('rdfs:label'),
+      ))
+      ->save();
+  }
+
+  /**
+   * Tests if file fields in teasers have correct resources.
+   *
+   * Ensure that file fields have the correct resource as the object in RDFa
+   * when displayed as a teaser.
+   */
+  function testNodeTeaser() {
+    // Set the teaser display to show this field.
+    entity_get_display('node', 'article', 'teaser')
+      ->setComponent($this->fieldName, array(
+        'type' => 'taxonomy_term_reference_link',
+      ))
+      ->save();
+
+    // Create a term in each vocabulary.
+    $term1 = $this->createTerm($this->vocabulary);
+    $term2 = $this->createTerm($this->vocabulary);
+    $taxonomy_term_1_uri = url('taxonomy/term/' . $term1->id(), array('absolute' => TRUE));
+    $taxonomy_term_2_uri = url('taxonomy/term/' . $term2->id(), array('absolute' => TRUE));
+
+    // Create the node.
+    $node = $this->drupalCreateNode(array('type' => 'article'));
+    $node->set($this->fieldName, array(
+      array('tid' => $term1->id()),
+      array('tid' => $term2->id()),
+    ));
+
+    // Render the node.
+    $node_render_array = entity_view_multiple(array($node), 'teaser');
+    $html = drupal_render($node_render_array);
+
+    // Parse the teaser.
+    $parser = new \EasyRdf_Parser_Rdfa();
+    $graph = new \EasyRdf_Graph();
+    $base_uri = url('<front>', array('absolute' => TRUE));
+    $parser->parse($graph, $html, 'rdfa', $base_uri);
+
+    // Node relations to taxonomy terms.
+    $node_uri = url('node/' . $node->nid, array('absolute' => TRUE));
+    $expected_value = array(
+      'type' => 'uri',
+      'value' => $taxonomy_term_1_uri,
+    );
+    $this->assertTrue($graph->hasProperty($node_uri, 'http://purl.org/dc/terms/subject', $expected_value), 'Node to term relation found in RDF output (dc:subject).');
+    $expected_value = array(
+      'type' => 'uri',
+      'value' => $taxonomy_term_2_uri,
+    );
+    $this->assertTrue($graph->hasProperty($node_uri, 'http://purl.org/dc/terms/subject', $expected_value), 'Node to term relation found in RDF output (dc:subject).');
+    // Taxonomy terms triples.
+    // Term 1.
+    $expected_value = array(
+      'type' => 'uri',
+      'value' => 'http://www.w3.org/2004/02/skos/core#Concept',
+    );
+    $this->assertTrue($graph->hasProperty($taxonomy_term_1_uri, 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type', $expected_value), 'Taxonomy term type found in RDF output (skos:Concept).');
+    $expected_value = array(
+      'type' => 'literal',
+      'value' => $term1->label(),
+    );
+    $this->assertTrue($graph->hasProperty($taxonomy_term_1_uri, 'http://www.w3.org/2000/01/rdf-schema#label', $expected_value), 'Taxonomy term name found in RDF output (rdfs:label).');
+    // Term 2.
+    $expected_value = array(
+      'type' => 'uri',
+      'value' => 'http://www.w3.org/2004/02/skos/core#Concept',
+    );
+    $this->assertTrue($graph->hasProperty($taxonomy_term_2_uri, 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type', $expected_value), 'Taxonomy term type found in RDF output (skos:Concept).');
+    $expected_value = array(
+      'type' => 'literal',
+      'value' => $term2->label(),
+    );
+    $this->assertTrue($graph->hasProperty($taxonomy_term_2_uri, 'http://www.w3.org/2000/01/rdf-schema#label', $expected_value), 'Taxonomy term name found in RDF output (rdfs:label).');
+  }
+
+  /**
+   * Create the taxonomy term reference field for testing.
+   *
+   * @param $field_name
+   *   The name of the field to create.
+   * @param $vocabulary
+   *   The vocabulary that the field should use.
+   *
+   * @todo Move this to TaxonomyTestBase, like the other field modules.
+   */
+  protected function createTaxonomyTermReferenceField($field_name, $vocabulary) {
+    $field = array(
+      'field_name' => $field_name,
+      'type' => 'taxonomy_term_reference',
+      'cardinality' => FIELD_CARDINALITY_UNLIMITED,
+      'settings' => array(
+        'allowed_values' => array(
+          array(
+            'vocabulary' => $vocabulary->id(),
+            'parent' => '0',
+          ),
+        ),
+      )
+    );
+    field_create_field($field);
+    $instance = array(
+      'field_name' => $field_name,
+      'entity_type' => 'node',
+      'bundle' => 'article',
+    );
+    field_create_instance($instance);
+    entity_get_form_display('node', 'article', 'default')
+      ->setComponent($field_name, array(
+        'type' => 'options_select',
+      ))
+      ->save();
+    entity_get_display('node', 'article', 'full')
+      ->setComponent($field_name, array(
+        'type' => 'taxonomy_term_reference_link',
+      ))
+      ->save();
+  }
+}
diff --git a/core/modules/rdf/lib/Drupal/rdf/Tests/TrackerAttributesTest.php b/core/modules/rdf/lib/Drupal/rdf/Tests/TrackerAttributesTest.php
index 0e6e4bb..7694925 100644
--- a/core/modules/rdf/lib/Drupal/rdf/Tests/TrackerAttributesTest.php
+++ b/core/modules/rdf/lib/Drupal/rdf/Tests/TrackerAttributesTest.php
@@ -37,6 +37,48 @@ function setUp() {
     // Creates article content type.
     $this->drupalCreateContentType(array('type' => 'article', 'name' => t('Article')));
 
+    // Set bundle RDF mapping config for article.
+    $mapping = rdf_get_mapping('node', 'article');
+    // Set fields RDF mapping config for article.
+    $node_shared_field_mappings = array(
+      'title' => array(
+        'properties' => array('dc:title'),
+      ),
+      'created' => array(
+        'properties' => array('dc:date', 'dc:created'),
+        'datatype' => 'xsd:dateTime',
+        'datatype_callback' => 'date_iso8601',
+      ),
+      'changed' => array(
+        'properties' => array('dc:modified'),
+        'datatype' => 'xsd:dateTime',
+        'datatype_callback' => 'date_iso8601',
+      ),
+      'body' => array(
+        'properties' => array('content:encoded'),
+      ),
+      'uid' => array(
+        'properties' => array('sioc:has_creator'),
+        'mapping_type' => 'rel',
+      ),
+      'name' => array(
+        'properties' => array('foaf:name'),
+      ),
+      'comment_count' => array(
+        'properties' => array('sioc:num_replies'),
+        'datatype' => 'xsd:integer',
+      ),
+      'last_activity' => array(
+        'properties' => array('sioc:last_activity_date'),
+        'datatype' => 'xsd:dateTime',
+        'datatype_callback' => 'date_iso8601',
+      ),
+    );
+    // Iterate over field mappings and save.
+    foreach ($node_shared_field_mappings as $field_name => $field_mapping) {
+      $mapping->setFieldMapping($field_name, $field_mapping)->save();
+    }
+
     // Enables anonymous posting of content.
     user_role_change_permissions(DRUPAL_ANONYMOUS_RID, array(
       'create article content' => TRUE,
diff --git a/core/modules/rdf/lib/Drupal/rdf/Tests/UserAttributesTest.php b/core/modules/rdf/lib/Drupal/rdf/Tests/UserAttributesTest.php
index 29c69cb..8de5927 100644
--- a/core/modules/rdf/lib/Drupal/rdf/Tests/UserAttributesTest.php
+++ b/core/modules/rdf/lib/Drupal/rdf/Tests/UserAttributesTest.php
@@ -19,7 +19,7 @@ class UserAttributesTest extends WebTestBase {
    *
    * @var array
    */
-  public static $modules = array('rdf', 'rdf_test');
+  public static $modules = array('rdf');
 
   public static function getInfo() {
     return array(
@@ -29,6 +29,18 @@ public static function getInfo() {
     );
   }
 
+  public function setUp() {
+    parent::setUp();
+    rdf_get_mapping('user', 'user')
+      ->setBundleMapping(array(
+        'types' => array('sioc:UserAccount'),
+      ))
+      ->setFieldMapping('name', array(
+        'properties' => array('foaf:name'),
+      ))
+      ->save();
+  }
+
   /**
    * Tests if default mapping for user is being used.
    *
@@ -39,7 +51,6 @@ function testUserAttributesInMarkup() {
     // Creates two users, one with access to user profiles.
     $user1 = $this->drupalCreateUser(array('access user profiles'));
     $user2 = $this->drupalCreateUser();
-    $username = $user2->name;
     $this->drupalLogin($user1);
 
     $account_uri = url('user/' . $user2->uid, array('absolute' => TRUE));
diff --git a/core/modules/rdf/rdf.api.php b/core/modules/rdf/rdf.api.php
index b3f95ba..a1a7c18 100644
--- a/core/modules/rdf/rdf.api.php
+++ b/core/modules/rdf/rdf.api.php
@@ -68,11 +68,11 @@ function hook_rdf_mapping() {
         ),
         'pid' => array(
           'predicates' => array('sioc:reply_of'),
-          'type' => 'rel',
+          'mapping_type' => 'rel',
         ),
         'uid' => array(
           'predicates' => array('sioc:has_creator'),
-          'type' => 'rel',
+          'mapping_type' => 'rel',
         ),
         'name' => array(
           'predicates' => array('foaf:name'),
diff --git a/core/modules/rdf/rdf.install b/core/modules/rdf/rdf.install
index 10d3f8d..be2cde1 100644
--- a/core/modules/rdf/rdf.install
+++ b/core/modules/rdf/rdf.install
@@ -4,46 +4,3 @@
  * @file
  * Install, update and uninstall functions for the rdf module.
  */
-
-/**
- * Implements hook_schema().
- */
-function rdf_schema() {
-  $schema['rdf_mapping'] = array(
-    'description' => 'Stores custom RDF mappings for user defined content types or overriden module-defined mappings',
-    'fields' => array(
-      'type' => array(
-        'type' => 'varchar',
-        'length' => 128,
-        'not null' => TRUE,
-        'description' => 'The name of the entity type a mapping applies to (node, user, comment, etc.).',
-      ),
-      'bundle' => array(
-        'type' => 'varchar',
-        'length' => 128,
-        'not null' => TRUE,
-        'description' => 'The name of the bundle a mapping applies to.',
-      ),
-      'mapping' => array(
-        'description' => 'The serialized mapping of the bundle type and fields to RDF terms.',
-        'type' => 'blob',
-        'not null' => FALSE,
-        'size' => 'big',
-        'serialize' => TRUE,
-      ),
-    ),
-    'primary key' => array('type', 'bundle'),
-  );
-
-  return $schema;
-}
-
-/**
- * Implements hook_install().
- */
-function rdf_install() {
-  // Collect any RDF mappings that were declared by modules installed before
-  // this one.
-  $modules = module_implements('rdf_mapping');
-  rdf_modules_installed($modules);
-}
diff --git a/core/modules/rdf/rdf.module b/core/modules/rdf/rdf.module
index aaea6bb..ba41fbb 100644
--- a/core/modules/rdf/rdf.module
+++ b/core/modules/rdf/rdf.module
@@ -43,38 +43,72 @@ function rdf_help($path, $arg) {
  *     'type' => 'node',
  *     'bundle' => RDF_DEFAULT_BUNDLE,
  *     'mapping' => array(
- *       'rdftype' => array('sioc:Item', 'foaf:Document'),
+ *       'types' => array('sioc:Item', 'foaf:Document'),
  *       'title' => array(
- *         'predicates' => array('dc:title'),
+ *         'properties' => array('dc:title'),
  *       ),
  *       'created' => array(
- *         'predicates' => array('dc:date', 'dc:created'),
+ *         'properties' => array('dc:date', 'dc:created'),
  *         'datatype' => 'xsd:dateTime',
- *         'callback' => 'date_iso8601',
+ *         'datatype_callback' => 'date_iso8601',
  *       ),
  *      'body' => array(
- *         'predicates' => array('content:encoded'),
+ *         'properties' => array('content:encoded'),
  *       ),
  *       'uid' => array(
- *         'predicates' => array('sioc:has_creator'),
+ *         'properties' => array('sioc:has_creator'),
  *       ),
  *       'name' => array(
- *         'predicates' => array('foaf:name'),
+ *         'properties' => array('foaf:name'),
  *       ),
  *     ),
  *   );
  * @endcode
  */
-
 /**
- * RDF bundle flag: Default bundle.
+ * Returns the RDF mapping object associated to a bundle.
+ *
+ * The function reads the rdf_mapping object from the current configuration,
+ * or returns a ready-to-use empty one if no configuration entry exists yet for
+ * this bundle. This streamlines the manipulation of mapping objects by always
+ * returning a consistent object that reflects the current state of the
+ * configuration.
+ *
+ * Example usage:
+ * -Map the 'article' bundle to 'sioc:Post' and the 'title' field to 'dc:title'.
+ * @code
+ * rdf_get_mapping('node', 'article')
+ *   ->setBundleMapping(array(
+ *     'types' => array('sioc:Post'),
+ *   ))
+ *   ->setFieldMapping('title', array(
+ *     'properties' => array('dc:title')
+ *   ))
+ *   ->save();
+ * @endcode
+ *
+ * @param string $entity_type
+ *   The entity type.
+ * @param string $bundle
+ *   The bundle.
  *
- * Implementations of hook_rdf_mapping() should use this constant for the
- * 'bundle' key when defining a default set of RDF mappings for an entity type.
- * Each bundle will inherit the default mappings defined for the entity type
- * unless the bundle defines its own specific mappings.
+ * @return \Drupal\rdf\Plugin\Core\Entity\RdfMapping
+ *   The RdfMapping object.
  */
-const RDF_DEFAULT_BUNDLE = '';
+function rdf_get_mapping($entity_type, $bundle) {
+  // Try loading the display from configuration.
+  $mapping = entity_load('rdf_mapping', $entity_type . '.' . $bundle);
+
+  // If not found, create a fresh mapping object.
+  if (!$mapping) {
+    $mapping = entity_create('rdf_mapping', array(
+      'targetEntityType' => $entity_type,
+      'bundle' => $bundle,
+    ));
+  }
+
+  return $mapping;
+}
 
 /**
  * Implements hook_rdf_namespaces().
@@ -113,167 +147,15 @@ function rdf_get_namespaces() {
 }
 
 /**
- * Returns the mapping for attributes of a given entity type/bundle pair.
- *
- * @param $type
- *   An entity type.
- * @param $bundle
- *   (optional) A bundle name.
- *
- * @return
- *   The mapping corresponding to the requested entity type/bundle pair or an
- *   empty array.
- */
-function rdf_mapping_load($type, $bundle = RDF_DEFAULT_BUNDLE) {
-  // Retrieves the bundle-specific mapping from the entity info.
-  $bundles = entity_get_bundles($type);
-  if (!empty($bundles[$bundle]['rdf_mapping'])) {
-    return $bundles[$bundle]['rdf_mapping'];
-  }
-  // If there is no mapping defined for this bundle, we return the default
-  // mapping that is defined for this entity type.
-  else {
-    return _rdf_get_default_mapping($type);
-  }
-}
-
-/**
  * @} End of "defgroup rdf".
  */
 
 /**
- * Gets the default RDF mapping for a given entity type.
- *
- * @param $type
- *   An entity type, e.g. 'node' or 'comment'.
- *
- * @return
- *   The RDF mapping or an empty array if no mapping is defined for this entity
- *   type.
- */
-function _rdf_get_default_mapping($type) {
-  $default_mappings = &drupal_static(__FUNCTION__);
-
-  if (!isset($default_mappings)) {
-    // Get all of the modules that implement hook_rdf_mapping().
-    $modules = module_implements('rdf_mapping');
-
-    // Only consider the default entity mapping definitions.
-    foreach ($modules as $module) {
-      $mappings = module_invoke($module, 'rdf_mapping');
-      foreach ($mappings as $mapping) {
-        if ($mapping['bundle'] === RDF_DEFAULT_BUNDLE) {
-          $default_mappings[$mapping['type']] = $mapping['mapping'];
-        }
-      }
-    }
-  }
-
-  return isset($default_mappings[$type]) ? $default_mappings[$type] : array();
-}
-
-/**
- * Retrieves an RDF mapping from the database.
- *
- * @param $type
- *   The entity type the mapping refers to.
- * @param $bundle
- *   The bundle the mapping refers to.
- *
- * @return
- *   An RDF mapping structure or, FALSE if the mapping does not exist.
- */
-function _rdf_mapping_load($type, $bundle) {
-  $mappings = _rdf_mapping_load_multiple($type, array($bundle));
-  return $mappings ? reset($mappings) : FALSE;
-}
-
-/**
- * Helper function to retrieve a set of RDF mappings from the database.
- *
- * @param $type
- *   The entity type of the mappings.
- * @param $bundles
- *   The bundles the mappings refer to.
- *
- * @return
- *   An array of RDF mapping structures, or an empty array.
- */
-function _rdf_mapping_load_multiple($type, array $bundles) {
-  $mappings = db_select('rdf_mapping')
-    ->fields(NULL, array('bundle', 'mapping'))
-    ->condition('type', $type)
-    ->condition('bundle', $bundles)
-    ->execute()
-    ->fetchAllKeyed();
-
-  foreach ($mappings as $bundle => $mapping) {
-    $mappings[$bundle] = unserialize($mapping);
-  }
-  return $mappings;
-}
-
-/**
  * @addtogroup rdf
  * @{
  */
 
 /**
- * Saves an RDF mapping to the database.
- *
- * Takes a mapping structure returned by hook_rdf_mapping() implementations
- * and creates or updates a record mapping for each encountered entity
- * type/bundle pair. If available, adds default values for non-existent mapping
- * keys.
- *
- * @param $mapping
- *   The RDF mapping to save.
- *
- * @return
- *   MergeQuery object that indicates the outcome of the operation.
- */
-function rdf_mapping_save($mapping) {
-  // In the case where a field has a mapping defined in the default entity
-  // mapping, but a mapping is not specified in the bundle-specific mapping,
-  // then use the default mapping for that field.
-  $mapping['mapping'] += _rdf_get_default_mapping($mapping['type']);
-
-  $status = db_merge('rdf_mapping')
-    ->key(array(
-      'type' => $mapping['type'],
-      'bundle' => $mapping['bundle'],
-    ))
-    ->fields(array(
-      'mapping' => serialize($mapping['mapping']),
-    ))
-    ->execute();
-
-  entity_info_cache_clear();
-
-  return $status;
-}
-
-/**
- * Deletes the mapping for the given bundle from the database.
- *
- * @param $type
- *   The entity type the mapping refers to.
- * @param $bundle
- *   The bundle the mapping refers to.
- *
- * @return
- *   TRUE if the mapping is deleted, FALSE if not.
- */
-function rdf_mapping_delete($type, $bundle) {
-  $num_rows = db_delete('rdf_mapping')
-    ->condition('type', $type)
-    ->condition('bundle', $bundle)
-    ->execute();
-
-  return (bool) ($num_rows > 0);
-}
-
-/**
  * Builds an array of RDFa attributes for a given mapping.
  *
  * This array will typically be passed through Drupal\Core\Template\Attribute
@@ -282,13 +164,13 @@ function rdf_mapping_delete($type, $bundle) {
  * field-specific $item_attributes variables.
  *
  * @param $mapping
- *   An array containing a mandatory 'predicates' key and optional 'datatype',
- *   'callback' and 'type' keys. For example:
+ *   An array containing a mandatory 'properties' key and optional 'datatype',
+ *   'datatype_callback' and 'type' keys. For example:
  *   @code
  *     array(
- *       'predicates' => array('dc:created'),
+ *       'properties' => array('dc:created'),
  *       'datatype' => 'xsd:dateTime',
- *       'callback' => 'date_iso8601',
+ *       'datatype_callback' => 'date_iso8601',
  *       ),
  *     );
  *   @endcode
@@ -302,29 +184,33 @@ function rdf_mapping_delete($type, $bundle) {
  * @see theme_rdf_template_variable_wrapper()
  */
 function rdf_rdfa_attributes($mapping, $data = NULL) {
+  $attributes = array();
+
   // The type of mapping defaults to 'property'.
-  $type = isset($mapping['type']) ? $mapping['type'] : 'property';
+  $type = isset($mapping['mapping_type']) ? $mapping['mapping_type'] : 'property';
 
   switch ($type) {
     // The mapping expresses the relationship between two resources.
     case 'rel':
     case 'rev':
-      $attributes[$type] = $mapping['predicates'];
+      $attributes[$type] = $mapping['properties'];
       break;
 
     // The mapping expresses the relationship between a resource and some
     // literal text.
     case 'property':
-      $attributes['property'] = $mapping['predicates'];
-      // Convert $data to a specific format as per the callback function.
-      if (isset($data) && isset($mapping['callback'])) {
-        $callback = $mapping['callback'];
-        $attributes['content'] = $callback($data);
-      }
-      if (isset($mapping['datatype'])) {
-        $attributes['datatype'] = $mapping['datatype'];
+      if (!empty($mapping['properties'])) {
+        $attributes['property'] = $mapping['properties'];
+        // Convert $data to a specific format as per the callback function.
+        if (isset($data) && isset($mapping['datatype_callback'])) {
+          $callback = $mapping['datatype_callback'];
+          $attributes['content'] = $callback($data);
+        }
+        if (isset($mapping['datatype'])) {
+          $attributes['datatype'] = $mapping['datatype'];
+        }
+        break;
       }
-      break;
   }
 
   return $attributes;
@@ -335,88 +221,18 @@ function rdf_rdfa_attributes($mapping, $data = NULL) {
  */
 
 /**
- * Implements hook_modules_installed().
- *
- * Checks if the installed modules have any RDF mapping definitions to declare
- * and stores them in the rdf_mapping table.
- *
- * While both default entity mappings and specific bundle mappings can be
- * defined in hook_rdf_mapping(), default entity mappings are not stored in the
- * database. Only overridden mappings are stored in the database. The default
- * entity mappings can be overriden by specific bundle mappings which are
- * stored in the database and can be altered via the RDF CRUD mapping API.
- */
-function rdf_modules_installed($modules) {
-  foreach ($modules as $module) {
-    $function = $module . '_rdf_mapping';
-    if (function_exists($function)) {
-      foreach ($function() as $mapping) {
-        // Only the bundle mappings are saved in the database.
-        if ($mapping['bundle'] !== RDF_DEFAULT_BUNDLE) {
-          rdf_mapping_save($mapping);
-        }
-      }
-    }
-  }
-}
-
-/**
- * Implements hook_modules_uninstalled().
- */
-function rdf_modules_uninstalled($modules) {
-  // @todo Remove RDF mappings of uninstalled modules.
-}
-
-/**
- * Implements hook_entity_bundle_info_alter().
- *
- * Adds the proper RDF mapping to each entity type/bundle pair.
- *
- * @todo May need to move the comment below to another place.
- * This hook should not be used by modules to alter the bundle mappings. The UI
- * should always be authoritative. UI mappings are stored in the database and
- * if hook_entity_info_alter() was used to override module defined mappings, it
- * would override the user defined mapping as well.
- *
- */
-function rdf_entity_bundle_info_alter(&$bundles) {
-  // Loop through each entity type and its bundles.
-  foreach ($bundles as $entity_type => $bundle_info) {
-    $bundle_names = array_keys($bundle_info);
-    $mappings = _rdf_mapping_load_multiple($entity_type, $bundle_names);
-
-    foreach ($bundle_names as $bundle) {
-      if (isset($mappings[$bundle])) {
-        $bundles[$entity_type][$bundle]['rdf_mapping'] = $mappings[$bundle];
-      }
-      else {
-        // If no mapping was found in the database, assign the default RDF
-        // mapping for this entity type.
-        $bundles[$entity_type][$bundle]['rdf_mapping'] = _rdf_get_default_mapping($entity_type);
-      }
-    }
-  }
-}
-
-/**
- * Implements hook_entity_load().
- */
-function rdf_entity_load($entities, $type) {
-  foreach ($entities as $entity) {
-    // Extracts the bundle of the entity being loaded.
-    $entity->rdf_mapping = rdf_mapping_load($type, $entity->bundle());
-  }
-}
-
-/**
  * Implements hook_comment_load().
+ *
+ * @todo refactor to take advantage of the new Drupal 8 APIs.
  */
 function rdf_comment_load($comments) {
   foreach ($comments as $comment) {
     // Pages with many comments can show poor performance. This information
     // isn't needed until rdf_preprocess_comment() is called, but set it here
     // to optimize performance for websites that implement an entity cache.
-    $comment->rdf_data['date'] = rdf_rdfa_attributes($comment->rdf_mapping['created'], $comment->created->value);
+    $created_mapping = rdf_get_mapping('comment', $comment->bundle())
+      ->getFieldMapping('created');
+    $comment->rdf_data['date'] = rdf_rdfa_attributes($created_mapping, $comment->created->value);
     $comment->rdf_data['nid_uri'] = url('node/' . $comment->nid->target_id);
     if ($comment->pid->target_id) {
       $comment->rdf_data['pid_uri'] = url('comment/' . $comment->pid->target_id, array('fragment' => 'comment-' . $comment->pid->target_id));
@@ -499,14 +315,18 @@ function rdf_preprocess_node(&$variables) {
   // URI of the resource described within the HTML element, while the @typeof
   // attribute indicates its RDF type (e.g., foaf:Document, sioc:Person, and so
   // on.)
+  $bundle = $variables['node']->bundle();
+  $mapping = rdf_get_mapping('node', $bundle);
+  $bundle_mapping = $mapping->getBundleMapping('node', $bundle);
   $variables['attributes']['about'] = empty($variables['node_url']) ? NULL: $variables['node_url'];
-  $variables['attributes']['typeof'] = empty($variables['node']->rdf_mapping['rdftype']) ? NULL : $variables['node']->rdf_mapping['rdftype'];
+  $variables['attributes']['typeof'] = empty($bundle_mapping['types']) ? NULL : $bundle_mapping['types'];
 
   // Adds RDFa markup to the title of the node. Because the RDFa markup is
   // added to the <h2> tag which might contain HTML code, we specify an empty
   // datatype to ensure the value of the title read by the RDFa parsers is a
   // literal.
-  $variables['title_attributes']['property'] = empty($variables['node']->rdf_mapping['title']['predicates']) ? NULL : $variables['node']->rdf_mapping['title']['predicates'];
+  $title_mapping = $mapping->getFieldMapping('title');
+  $variables['title_attributes']['property'] = empty($title_mapping['properties']) ? NULL : $title_mapping['properties'];
   $variables['title_attributes']['datatype'] = '';
 
   // In full node mode, the title is not displayed by node.html.twig so it is
@@ -519,35 +339,40 @@ function rdf_preprocess_node(&$variables) {
         'about' => $variables['node_url'],
       ),
     );
-    if (!empty($variables['node']->rdf_mapping['title']['predicates'])) {
-      $element['#attributes']['property'] = $variables['node']->rdf_mapping['title']['predicates'];
+    if (!empty($title_mapping['properties'])) {
+      $element['#attributes']['property'] = $title_mapping['properties'];
     }
     drupal_add_html_head($element, 'rdf_node_title');
   }
 
   // Adds RDFa markup for the date.
-  if (!empty($variables['node']->rdf_mapping['created'])) {
-    $date_attributes = rdf_rdfa_attributes($variables['node']->rdf_mapping['created'], $variables['node']->created);
+  $created_mapping = $mapping->getFieldMapping('created');
+  if (!empty($created_mapping)) {
+    $date_attributes = rdf_rdfa_attributes($created_mapping, $variables['node']->created);
     $variables['rdf_template_variable_attributes']['date'] = $date_attributes;
     if ($variables['submitted']) {
       $variables['rdf_template_variable_attributes']['submitted'] = $date_attributes;
     }
   }
   // Adds RDFa markup for the relation between the node and its author.
-  if (!empty($variables['node']->rdf_mapping['uid'])) {
-    $variables['rdf_template_variable_attributes']['name']['rel'] = $variables['node']->rdf_mapping['uid']['predicates'];
+  $uid_mapping = $mapping->getFieldMapping('uid');
+  if (!empty($uid_mapping)) {
+    $variables['rdf_template_variable_attributes']['name']['rel'] = $uid_mapping['properties'];
     if ($variables['submitted']) {
-      $variables['rdf_template_variable_attributes']['submitted']['rel'] = $variables['node']->rdf_mapping['uid']['predicates'];
+      $variables['rdf_template_variable_attributes']['submitted']['rel'] = $uid_mapping['properties'];
     }
   }
 
   // Adds RDFa markup annotating the number of comments a node has.
-  if (isset($variables['node']->comment_count) && !empty($variables['node']->rdf_mapping['comment_count']['predicates'])) {
+  $comment_count_mapping = $mapping->getFieldMapping('comment_count');
+  if (isset($variables['node']->comment_count) && !empty($comment_count_mapping['properties'])) {
     // Annotates the 'x comments' link in teaser view.
     if (isset($variables['content']['links']['comment']['#links']['comment-comments'])) {
-      $comment_count_attributes['property'] = $variables['node']->rdf_mapping['comment_count']['predicates'];
+      $comment_count_attributes['property'] = $comment_count_mapping['properties'];
       $comment_count_attributes['content'] = $variables['node']->comment_count;
-      $comment_count_attributes['datatype'] = $variables['node']->rdf_mapping['comment_count']['datatype'];
+      if (isset($comment_count_mapping['datatype'])) {
+        $comment_count_attributes['datatype'] = $comment_count_mapping['datatype'];
+      }
       // According to RDFa parsing rule number 4, a new subject URI is created
       // from the href attribute if no rel/rev attribute is present. To get the
       // original node URL from the about attribute of the parent container we
@@ -564,9 +389,9 @@ function rdf_preprocess_node(&$variables) {
         '#tag' => 'meta',
         '#attributes' => array(
           'about' => $variables['node_url'],
-          'property' => $variables['node']->rdf_mapping['comment_count']['predicates'],
+          'property' => $comment_count_mapping['properties'],
           'content' => $variables['node']->comment_count,
-          'datatype' => $variables['node']->rdf_mapping['comment_count']['datatype'],
+          'datatype' => isset($comment_count_mapping['datatype']) ? $comment_count_mapping['datatype'] : NULL,
         ),
       );
       drupal_add_html_head($element, 'rdf_node_comment_count');
@@ -579,12 +404,15 @@ function rdf_preprocess_node(&$variables) {
  */
 function rdf_preprocess_field(&$variables) {
   $element = $variables['element'];
-  $mapping = rdf_mapping_load($element['#entity_type'], $element['#bundle']);
+  $entity_type = $element['#entity_type'];
+  $bundle = $element['#bundle'];
   $field_name = $element['#field_name'];
+  $field_mapping = rdf_get_mapping($entity_type, $bundle)
+    ->getFieldMapping($field_name);
 
-  if (!empty($mapping) && !empty($mapping[$field_name])) {
+  if (!empty($field_mapping)) {
     foreach ($element['#items'] as $delta => $item) {
-      $variables['item_attributes'][$delta] = rdf_rdfa_attributes($mapping[$field_name], $item);
+      $variables['item_attributes'][$delta] = rdf_rdfa_attributes($field_mapping, $item);
       // If this field is an image, RDFa will not output correctly when the
       // image is in a containing <a> tag. If the field is a file, RDFa will
       // not output correctly if the filetype icon comes before the link to the
@@ -608,11 +436,13 @@ function rdf_preprocess_field(&$variables) {
 function rdf_preprocess_user(&$variables) {
   $account = $variables['elements']['#user'];
   $uri = $account->uri();
+  $mapping = rdf_get_mapping('user', 'user');
+  $bundle_mapping = $mapping->getBundleMapping();
 
   // Adds RDFa markup to the user profile page. Fields displayed in this page
   // will automatically describe the user.
-  if (!empty($account->rdf_mapping['rdftype'])) {
-    $variables['attributes']['typeof'] = $account->rdf_mapping['rdftype'];
+  if (!empty($bundle_mapping['types'])) {
+    $variables['attributes']['typeof'] = $bundle_mapping['types'];
     $variables['attributes']['about'] = url($uri['path'], $uri['options']);
   }
   // If we are on the user account page, add the relationship between the
@@ -629,17 +459,20 @@ function rdf_preprocess_user(&$variables) {
     );
     // Adds the markup for username as language neutral literal, see
     // rdf_preprocess_username().
-    $username_meta = array(
-      '#tag' => 'meta',
-      '#attributes' => array(
-        'about' => url($uri['path'], $uri['options']),
-        'property' => $account->rdf_mapping['name']['predicates'],
-        'content' => $account->name,
-        'lang' => '',
-      )
-    );
+    $name_mapping = $mapping->getFieldMapping('name');
+    if (!empty($name_mapping['properties'])) {
+      $username_meta = array(
+        '#tag' => 'meta',
+        '#attributes' => array(
+          'about' => url($uri['path'], $uri['options']),
+          'property' => $name_mapping['properties'],
+          'content' => $account->name,
+          'lang' => '',
+        )
+      );
+      drupal_add_html_head($username_meta, 'rdf_user_username');
+    }
     drupal_add_html_head($account_holder_meta, 'rdf_user_account_holder');
-    drupal_add_html_head($username_meta, 'rdf_user_username');
   }
 }
 
@@ -656,16 +489,8 @@ function rdf_preprocess_username(&$variables) {
     $variables['attributes']['lang'] = '';
   }
 
-  // $variables['account'] is a pseudo account object, and as such, does not
-  // contain the RDF mappings for the user. In the case of nodes and comments,
-  // it contains the mappings for the node or comment object instead. However,
-  // while the RDF mappings are available from a full user_load(), this should
-  // be avoided for performance reasons. Since the type and bundle for users is
-  // already known, call rdf_mapping_load() directly.
-  $rdf_mapping = rdf_mapping_load('user', 'user');
-
   // The profile URI is used to identify the user account. The about attribute
-  // is used to set the URI as the default subject of the predicates embedded
+  // is used to set the URI as the default subject of the properties embedded
   // as RDFa in the child elements. Even if the user profile is not accessible
   // to the current user, we use its URI in order to identify the user in RDF.
   // We do not use this attribute for the anonymous user because we do not have
@@ -676,21 +501,24 @@ function rdf_preprocess_username(&$variables) {
   }
 
   $attributes = array();
-  // The typeof attribute specifies the RDF type(s) of this resource. They
-  // are defined in the 'rdftype' property of the user RDF mapping.
-  if (!empty($rdf_mapping['rdftype'])) {
-    $attributes['typeof'] = $rdf_mapping['rdftype'];
+  // Add RDF type of user.
+  $mapping = rdf_get_mapping('user', 'user');
+  $bundle_mapping = $mapping->getBundleMapping();
+  if (!empty($bundle_mapping['types'])) {
+    $attributes['typeof'] = $bundle_mapping['types'];
   }
   // Annotate the username in RDFa. A property attribute is used with an empty
   // datatype attribute to ensure the username is parsed as a plain literal
   // in RDFa 1.0 and 1.1.
-  if (!empty($rdf_mapping['name'])) {
-    $attributes['property'] = $rdf_mapping['name']['predicates'];
+  $name_mapping = $mapping->getFieldMapping('name');
+  if (!empty($name_mapping)) {
+    $attributes['property'] = $name_mapping['properties'];
     $attributes['datatype'] = '';
   }
   // Add the homepage RDFa markup if present.
-  if (!empty($variables['homepage']) && !empty($rdf_mapping['homepage'])) {
-    $attributes['rel'] = $rdf_mapping['homepage']['predicates'];
+  $homepage_mapping = $mapping->getFieldMapping('homepage');
+  if (!empty($variables['homepage']) && !empty($homepage_mapping)) {
+    $attributes['rel'] = $homepage_mapping['properties'];
   }
   // The remaining attributes can have multiple values listed, with whitespace
   // separating the values in the RDFa attributes
@@ -705,18 +533,22 @@ function rdf_preprocess_username(&$variables) {
  */
 function rdf_preprocess_comment(&$variables) {
   $comment = $variables['comment'];
-  if (!empty($comment->rdf_mapping['rdftype'])) {
+  $mapping = rdf_get_mapping('comment', $comment->bundle());
+  $bundle_mapping = $mapping->getBundleMapping();
+
+  if (!empty($bundle_mapping['types'])) {
     // Adds RDFa markup to the comment container. The about attribute specifies
     // the URI of the resource described within the HTML element, while the
     // typeof attribute indicates its RDF type (e.g., sioc:Post, foaf:Document,
     // and so on.)
     $uri = $comment->uri();
     $variables['attributes']['about'] = url($uri['path'], $uri['options']);
-    $variables['attributes']['typeof'] = $comment->rdf_mapping['rdftype'];
+    $variables['attributes']['typeof'] = $bundle_mapping['types'];
   }
 
   // Adds RDFa markup for the date of the comment.
-  if (!empty($comment->rdf_mapping['created'])) {
+  $created_mapping = $mapping->getFieldMapping('created');
+  if (!empty($created_mapping)) {
     // The comment date is precomputed as part of the rdf_data so that it can be
     // cached as part of the entity.
     $date_attributes = $comment->rdf_data['date'];
@@ -724,24 +556,27 @@ function rdf_preprocess_comment(&$variables) {
     $variables['rdf_template_variable_attributes']['submitted'] = $date_attributes;
   }
   // Adds RDFa markup for the relation between the comment and its author.
-  if (!empty($comment->rdf_mapping['uid'])) {
-    $variables['rdf_template_variable_attributes']['author']['rel'] = $comment->rdf_mapping['uid']['predicates'];
-    $variables['rdf_template_variable_attributes']['submitted']['rel'] = $comment->rdf_mapping['uid']['predicates'];
+  $uid_mapping = $mapping->getFieldMapping('uid');
+  if (!empty($uid_mapping)) {
+    $variables['rdf_template_variable_attributes']['author']['rel'] = $uid_mapping['properties'];
+    $variables['rdf_template_variable_attributes']['submitted']['rel'] = $uid_mapping['properties'];
   }
-  if (!empty($comment->rdf_mapping['title'])) {
+  $title_mapping = $mapping->getFieldMapping('title');
+  if (!empty($title_mapping)) {
     // Adds RDFa markup to the subject of the comment. Because the RDFa markup
     // is added to an <h3> tag which might contain HTML code, we specify an
     // empty datatype to ensure the value of the title read by the RDFa parsers
     // is a literal.
-    $variables['title_attributes']['property'] = $comment->rdf_mapping['title']['predicates'];
+    $variables['title_attributes']['property'] = $title_mapping['properties'];
     $variables['title_attributes']['datatype'] = '';
   }
 
   // Annotates the parent relationship between the current comment and the node
   // it belongs to. If available, the parent comment is also annotated.
-  if (!empty($comment->rdf_mapping['pid'])) {
+  $pid_mapping = $mapping->getFieldMapping('pid');
+  if (!empty($pid_mapping)) {
     // Adds the relation to the parent node.
-    $parent_node_attributes['rel'] = $comment->rdf_mapping['pid']['predicates'];
+    $parent_node_attributes['rel'] = $pid_mapping['properties'];
     // The parent node URI is precomputed as part of the rdf_data so that it can
     // be cached as part of the entity.
     $parent_node_attributes['resource'] = $comment->rdf_data['nid_uri'];
@@ -749,7 +584,7 @@ function rdf_preprocess_comment(&$variables) {
 
     // Adds the relation to parent comment, if it exists.
     if ($comment->pid->target_id != 0) {
-      $parent_comment_attributes['rel'] = $comment->rdf_mapping['pid']['predicates'];
+      $parent_comment_attributes['rel'] = $pid_mapping['properties'];
       // The parent comment URI is precomputed as part of the rdf_data so that
       // it can be cached as part of the entity.
       $parent_comment_attributes['resource'] = $comment->rdf_data['pid_uri'];
@@ -762,14 +597,17 @@ function rdf_preprocess_comment(&$variables) {
  * Implements hook_preprocess_HOOK() for taxonomy-term.tpl.php.
  */
 function rdf_preprocess_taxonomy_term(&$variables) {
-  // Adds the RDF type of the term and the term name in a <meta> tag.
   $term = $variables['term'];
+  $mapping = rdf_get_mapping('taxonomy_term', $term->bundle());
+  $bundle_mapping = $mapping->getBundleMapping();
+  $name_field_mapping = $mapping->getFieldMapping('name');
+  // Adds the RDF type of the term and the term name in a <meta> tag.
   $term_label_meta = array(
       '#tag' => 'meta',
       '#attributes' => array(
         'about' => url('taxonomy/term/' . $term->id()),
-        'typeof' => $term->rdf_mapping['rdftype'],
-        'property' => $term->rdf_mapping['name']['predicates'],
+        'typeof' => $bundle_mapping['types'],
+        'property' => $name_field_mapping['properties'],
         'content' => $term->label(),
       ),
     );
@@ -790,13 +628,16 @@ function rdf_field_attach_view_alter(&$output, $context) {
         // yet and thus have no $item['entity'].
         if (isset($item['entity'])) {
           $term = $item['entity'];
-          if (!empty($term->rdf_mapping['rdftype'])) {
-            $element[$delta]['#options']['attributes']['typeof'] = $term->rdf_mapping['rdftype'];
+          $mapping = rdf_get_mapping('taxonomy_term', $term->bundle());
+          $bundle_mapping = $mapping->getBundleMapping();
+          if (!empty($bundle_mapping['types'])) {
+            $element[$delta]['#options']['attributes']['typeof'] = $bundle_mapping['types'];
           }
-          if (!empty($term->rdf_mapping['name']['predicates'])) {
+          $name_field_mapping = $mapping->getFieldMapping('name');
+          if (!empty($name_field_mapping['properties'])) {
             // A property attribute is used with an empty datatype attribute so
             // the term name is parsed as a plain literal in RDFa 1.0 and 1.1.
-            $element[$delta]['#options']['attributes']['property'] = $term->rdf_mapping['name']['predicates'];
+            $element[$delta]['#options']['attributes']['property'] = $name_field_mapping['properties'];
             $element[$delta]['#options']['attributes']['datatype'] = '';
           }
         }
diff --git a/core/modules/rdf/rdf.services.yml b/core/modules/rdf/rdf.services.yml
deleted file mode 100644
index 9777720..0000000
--- a/core/modules/rdf/rdf.services.yml
+++ /dev/null
@@ -1,11 +0,0 @@
-services:
-  rdf.site_schema_manager:
-    class: Drupal\rdf\SiteSchema\SiteSchemaManager
-    arguments: ['@cache.cache']
-  rdf.mapping_manager:
-    class: Drupal\rdf\RdfMappingManager
-    arguments: ['@event_dispatcher', '@rdf.site_schema_manager']
-  rdf.mapping:
-    class: Drupal\rdf\EventSubscriber\MappingSubscriber
-    tags:
-      - { name: event_subscriber }
diff --git a/core/modules/rdf/tests/rdf_test.info.yml b/core/modules/rdf/tests/rdf_test.info.yml
deleted file mode 100644
index c39c5b9..0000000
--- a/core/modules/rdf/tests/rdf_test.info.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-name: 'RDF module tests'
-type: module
-description: 'Support module for RDF module testing.'
-package: Testing
-version: VERSION
-core: 8.x
-hidden: true
-dependencies:
-  - rdf
diff --git a/core/modules/rdf/tests/rdf_test.install b/core/modules/rdf/tests/rdf_test.install
deleted file mode 100644
index 91a3392..0000000
--- a/core/modules/rdf/tests/rdf_test.install
+++ /dev/null
@@ -1,25 +0,0 @@
-<?php
-
-/**
- * @file
- * Install, update and uninstall functions for the rdf module.
- */
-
-/**
- * Implements hook_install().
- */
-function rdf_test_install() {
-  $rdf_mappings = array(
-    array(
-      'type' => 'node',
-      'bundle' => 'test_bundle_hook_install',
-      'mapping' => array(
-        'rdftype' => array('foo:mapping_install1', 'bar:mapping_install2'),
-      ),
-    ),
-  );
-
-  foreach ($rdf_mappings as $rdf_mapping) {
-    rdf_mapping_save($rdf_mapping);
-  }
-}
diff --git a/core/modules/rdf/tests/rdf_test.module b/core/modules/rdf/tests/rdf_test.module
deleted file mode 100644
index 4d90472..0000000
--- a/core/modules/rdf/tests/rdf_test.module
+++ /dev/null
@@ -1,59 +0,0 @@
-<?php
-
-/**
- * @file
- * Tests API interaction with the RDF module.
- */
-
-/**
- * Implements hook_rdf_mapping().
- */
-function rdf_test_rdf_mapping() {
-  return array(
-    array(
-      'type' => 'test_entity',
-      'bundle' => 'test_bundle',
-      'mapping' => array(
-        'rdftype' => array('sioc:Post'),
-        'title' => array(
-          'predicates' => array('dc:title'),
-        ),
-        'created' => array(
-          'predicates' => array('dc:created'),
-          'datatype' => 'xsd:dateTime',
-          'callback' => 'date_iso8601',
-        ),
-        'uid' => array(
-          'predicates' => array('sioc:has_creator', 'dc:creator'),
-          'type' => 'rel',
-        ),
-        'foobar' => array(
-          'predicates' => array('foo:bar'),
-        ),
-        'foobar1' => array(
-          'datatype' => 'foo:bar1type',
-          'predicates' => array('foo:bar1'),
-        ),
-        'foobar_objproperty1' => array(
-          'predicates' => array('sioc:has_creator', 'dc:creator'),
-          'type' => 'rel',
-        ),
-        'foobar_objproperty2' => array(
-          'predicates' => array('sioc:reply_of'),
-          'type' => 'rev',
-        ),
-      ),
-    ),
-  );
-}
-
-/**
- * Implements hook_rdf_namespaces().
- */
-function rdf_test_rdf_namespaces() {
-  return array(
-    'dc'       => 'http://purl.org/conflicting/namespace',
-    'foaf'     => 'http://xmlns.com/foaf/0.1/',
-    'foaf1'    => 'http://xmlns.com/foaf/0.1/',
-  );
-}
diff --git a/core/modules/rdf/tests/rdf_test_mapping/lib/Drupal/rdf_test_mapping/EventSubscriber/TestMappingSubscriber.php b/core/modules/rdf/tests/rdf_test_mapping/lib/Drupal/rdf_test_mapping/EventSubscriber/TestMappingSubscriber.php
deleted file mode 100644
index 44e9460..0000000
--- a/core/modules/rdf/tests/rdf_test_mapping/lib/Drupal/rdf_test_mapping/EventSubscriber/TestMappingSubscriber.php
+++ /dev/null
@@ -1,58 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains TestMappingSubscriber.
- */
-
-namespace Drupal\rdf_test_mapping\EventSubscriber;
-
-use Drupal\rdf\RdfMappingEvents;
-use Drupal\rdf\SiteSchema\BundleSchema;
-use Drupal\rdf\SiteSchema\SiteSchema;
-use Symfony\Component\EventDispatcher\EventSubscriberInterface;
-
-class TestMappingSubscriber implements EventSubscriberInterface {
-
-  const STAGING_SITE_TYPE_URI = 'http://staging.com/entity_test_bundle';
-
-  /**
-   * Demonstrate mapping between external type and site schema type.
-   *
-   * @param \Drupal\rdf\MapTypesFromInputEvent $event
-   *   The mapping event.
-   */
-  public function mapTypesFromInput($event) {
-    $input_uris = $event->getInputUris();
-    $site_schema_types = $event->getSiteSchemaTypes();
-
-    // This mapping between an external type and a site schema type would be
-    // managed by something in the implementing module, such as a database
-    // table. For the test, manually map a fake external URI to the site schema
-    // URI for the test entity.
-    $schema = new SiteSchema(SiteSchema::CONTENT_DEPLOYMENT);
-    $bundle_schema = $schema->bundle('entity_test', 'entity_test');
-    $site_schema_type = $bundle_schema->getUri();
-    $mapping = array(
-      self::STAGING_SITE_TYPE_URI => $site_schema_type,
-    );
-
-    foreach ($input_uris as $input_uri) {
-      // If the incoming URI is mapped in the mapping array, and the value of
-      // that mapping is found in the cache of site schema types, then set the
-      // site schema URI.
-      if (isset($mapping[$input_uri]) && isset($site_schema_types[$mapping[$input_uri]])) {
-        $event->setSiteSchemaUri($mapping[$input_uri]);
-      }
-    }
-  }
-
-  /**
-   * Implements EventSubscriberInterface::getSubscribedEvents().
-   */
-  static function getSubscribedEvents() {
-    $events[RdfMappingEvents::MAP_TYPES_FROM_INPUT] = 'mapTypesFromInput';
-    return $events;
-  }
-
-}
diff --git a/core/modules/rdf/tests/rdf_test_mapping/rdf_test_mapping.info.yml b/core/modules/rdf/tests/rdf_test_mapping/rdf_test_mapping.info.yml
deleted file mode 100644
index b5a7bcc..0000000
--- a/core/modules/rdf/tests/rdf_test_mapping/rdf_test_mapping.info.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-name: 'RDF module mapping test'
-type: module
-description: 'Test mapping subscriber for RDF mapping tests.'
-package: Testing
-core: 8.x
-hidden: true
-dependencies:
-  - rdf
diff --git a/core/modules/rdf/tests/rdf_test_mapping/rdf_test_mapping.module b/core/modules/rdf/tests/rdf_test_mapping/rdf_test_mapping.module
deleted file mode 100644
index b3d9bbc..0000000
--- a/core/modules/rdf/tests/rdf_test_mapping/rdf_test_mapping.module
+++ /dev/null
@@ -1 +0,0 @@
-<?php
diff --git a/core/modules/rdf/tests/rdf_test_mapping/rdf_test_mapping.services.yml b/core/modules/rdf/tests/rdf_test_mapping/rdf_test_mapping.services.yml
deleted file mode 100644
index 0cb945e..0000000
--- a/core/modules/rdf/tests/rdf_test_mapping/rdf_test_mapping.services.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-services:
-  rdf_test_mapping.mapping:
-    class: Drupal\rdf_test_mapping\EventSubscriber\TestMappingSubscriber
-    tags:
-      - { name: event_subscriber }
diff --git a/core/modules/rdf/tests/rdf_test_namespaces/rdf_test_namespaces.info.yml b/core/modules/rdf/tests/rdf_test_namespaces/rdf_test_namespaces.info.yml
new file mode 100644
index 0000000..99cee1a
--- /dev/null
+++ b/core/modules/rdf/tests/rdf_test_namespaces/rdf_test_namespaces.info.yml
@@ -0,0 +1,8 @@
+name: 'RDF module namespaces test'
+type: module
+description: 'Test namespace declaration.'
+package: Testing
+core: 8.x
+hidden: true
+dependencies:
+  - rdf
diff --git a/core/modules/rdf/tests/rdf_test_namespaces/rdf_test_namespaces.module b/core/modules/rdf/tests/rdf_test_namespaces/rdf_test_namespaces.module
new file mode 100644
index 0000000..c938927
--- /dev/null
+++ b/core/modules/rdf/tests/rdf_test_namespaces/rdf_test_namespaces.module
@@ -0,0 +1,17 @@
+<?php
+
+/**
+ * @file
+ * Test the namespace registration functionality.
+ */
+
+/**
+ * Implements hook_rdf_namespaces().
+ */
+function rdf_test_namespaces_rdf_namespaces() {
+  return array(
+    'dc'       => 'http://purl.org/conflicting/namespace',
+    'foaf'     => 'http://xmlns.com/foaf/0.1/',
+    'foaf1'    => 'http://xmlns.com/foaf/0.1/',
+  );
+}
diff --git a/core/modules/taxonomy/taxonomy.module b/core/modules/taxonomy/taxonomy.module
index 8865e17..6e9ae7f 100644
--- a/core/modules/taxonomy/taxonomy.module
+++ b/core/modules/taxonomy/taxonomy.module
@@ -1089,51 +1089,6 @@ function taxonomy_field_settings_form($field, $instance, $has_data) {
 }
 
 /**
- * Implements hook_rdf_mapping().
- *
- * @return array
- *   The rdf mapping for vocabularies and terms.
- */
-function taxonomy_rdf_mapping() {
-  return array(
-    array(
-      'type' => 'taxonomy_term',
-      'bundle' => RDF_DEFAULT_BUNDLE,
-      'mapping' => array(
-        'rdftype' => array('skos:Concept'),
-        'name'   => array(
-          'predicates' => array('rdfs:label', 'skos:prefLabel'),
-        ),
-        'description'   => array(
-          'predicates' => array('skos:definition'),
-        ),
-        'vid'   => array(
-          'predicates' => array('skos:inScheme'),
-          'type' => 'rel',
-        ),
-        'parent'   => array(
-          'predicates' => array('skos:broader'),
-          'type' => 'rel',
-        ),
-      ),
-    ),
-    array(
-      'type' => 'taxonomy_vocabulary',
-      'bundle' => RDF_DEFAULT_BUNDLE,
-      'mapping' => array(
-        'rdftype' => array('skos:ConceptScheme'),
-        'name'   => array(
-          'predicates' => array('dc:title'),
-        ),
-        'description'   => array(
-          'predicates' => array('rdfs:comment'),
-        ),
-      ),
-    ),
-  );
-}
-
-/**
  * @defgroup taxonomy_index Taxonomy indexing
  * @{
  * Functions to maintain taxonomy indexing.
diff --git a/core/modules/tracker/tracker.pages.inc b/core/modules/tracker/tracker.pages.inc
index be5302e..6f19ec5 100644
--- a/core/modules/tracker/tracker.pages.inc
+++ b/core/modules/tracker/tracker.pages.inc
@@ -84,34 +84,37 @@ function tracker_page($account = NULL, $set_title = FALSE) {
       );
 
       // Adds extra RDFa markup to the $row array if the RDF module is enabled.
-      if (function_exists('rdf_mapping_load')) {
-        // Each node is not loaded for performance reasons, as a result we need
-        // to retrieve the RDF mapping for each node type.
-        $mapping = rdf_mapping_load('node', $node->type);
+      if (module_exists('rdf')) {
+        $mapping = rdf_get_mapping('node', $node->type);
         // Adds RDFa markup to the title of the node. Because the RDFa markup is
         // added to the td tag which might contain HTML code, we specify an
         // empty datatype to ensure the value of the title read by the RDFa
         // parsers is a plain literal.
-        $row['title'] += rdf_rdfa_attributes($mapping['title']) + array('datatype' => '');
+        $title_mapping = $mapping->getFieldMapping('title');
+        $row['title'] += rdf_rdfa_attributes($title_mapping) + array('datatype' => '');
         // Annotates the td tag containing the author of the node.
-        $row['author'] += rdf_rdfa_attributes($mapping['uid']);
+        $uid_mapping = $mapping->getFieldMapping('uid');
+        $row['author'] += rdf_rdfa_attributes($uid_mapping);
         // Annotates the td tag containing the number of replies. We add the
         // content attribute to ensure that only the comment count is used as
         // the value for 'num_replies'. Otherwise, other text such as a link
         // to the number of new comments could be included in the 'num_replies'
         // value.
-        $row['replies'] += rdf_rdfa_attributes($mapping['comment_count']);
+        $comment_count_mapping = $mapping->getFieldMapping('comment_count');
+        $row['replies'] += rdf_rdfa_attributes($comment_count_mapping);
         $row['replies'] += array('content' => $node->comment_count);
         // If the node has no comments, we assume the node itself was modified
         // and apply 'changed' in addition to 'last_activity'.  If there are
         // comments present, we cannot infer whether the node itself was
         // modified or a comment was posted, so we use only 'last_activity'.
-        $mapping_last_activity = rdf_rdfa_attributes($mapping['last_activity'], $node->last_activity);
+        $last_activity_mapping = $mapping->getFieldMapping('last_activity');
+        $last_activity_attributes = rdf_rdfa_attributes($last_activity_mapping, $node->last_activity);
         if ($node->comment_count == 0) {
-          $mapping_changed = rdf_rdfa_attributes($mapping['changed'], $node->last_activity);
-          $mapping_last_activity['property'] = array_merge($mapping_last_activity['property'], $mapping_changed['property']);
+          $changed_mapping = $mapping->getFieldMapping('changed');
+          $changed_attributes = rdf_rdfa_attributes($changed_mapping, $node->last_activity);
+          $last_activity_attributes['property'] = array_merge($last_activity_attributes['property'], $changed_attributes['property']);
         }
-        $row['last updated'] += $mapping_last_activity;
+        $row['last updated'] += $last_activity_attributes;
 
         // We need to add the about attribute on the tr tag to specify which
         // node the RDFa annotations above apply to. We move the content of
diff --git a/core/modules/user/user.module b/core/modules/user/user.module
index 28083e0..03c8155 100644
--- a/core/modules/user/user.module
+++ b/core/modules/user/user.module
@@ -2551,28 +2551,6 @@ function user_cookie_delete($cookie_name) {
 }
 
 /**
- * Implements hook_rdf_mapping().
- */
-function user_rdf_mapping() {
-  return array(
-    array(
-      'type' => 'user',
-      'bundle' => RDF_DEFAULT_BUNDLE,
-      'mapping' => array(
-        'rdftype' => array('sioc:UserAccount'),
-        'name' => array(
-          'predicates' => array('foaf:name'),
-        ),
-        'homepage' => array(
-          'predicates' => array('foaf:page'),
-          'type' => 'rel',
-        ),
-      ),
-    ),
-  );
-}
-
-/**
  * Implements hook_file_download_access().
  */
 function user_file_download_access($field, EntityInterface $entity, File $file) {
diff --git a/core/profiles/standard/config/rdf.mapping.comment.comment_node_article.yml b/core/profiles/standard/config/rdf.mapping.comment.comment_node_article.yml
new file mode 100644
index 0000000..487fe5d
--- /dev/null
+++ b/core/profiles/standard/config/rdf.mapping.comment.comment_node_article.yml
@@ -0,0 +1,35 @@
+id: comment.comment_node_article
+targetEntityType: comment
+bundle: comment_node_article
+types:
+  - 'sioc:Post'
+  - 'sioct:Comment'
+fieldMappings:
+  title:
+    properties:
+      - 'dc:title'
+  created:
+    properties:
+      - 'dc:date'
+      - 'dc:created'
+    datatype: 'xsd:dateTime'
+    datatype_callback: 'date_iso8601'
+  changed:
+    properties:
+      - 'dc:modified'
+    datatype: 'xsd:dateTime'
+    datatype_callback: 'date_iso8601'
+  comment_body:
+    properties:
+      - 'content:encoded'
+  uid:
+    properties:
+      - 'sioc:has_creator'
+    mapping_type: 'rel'
+  name:
+    properties:
+      - 'foaf:name'
+  pid:
+    properties:
+      - 'sioc:reply_of'
+    mapping_type: 'rel'
diff --git a/core/profiles/standard/config/rdf.mapping.node.article.yml b/core/profiles/standard/config/rdf.mapping.node.article.yml
new file mode 100644
index 0000000..ac31562
--- /dev/null
+++ b/core/profiles/standard/config/rdf.mapping.node.article.yml
@@ -0,0 +1,49 @@
+id: node.article
+targetEntityType: node
+bundle: article
+types:
+  - 'foaf:Document'
+  - 'sioc:Item'
+fieldMappings:
+  title:
+    properties:
+      - 'dc:title'
+  created:
+    properties:
+      - 'dc:date'
+      - 'dc:created'
+    datatype: 'xsd:dateTime'
+    datatype_callback: 'date_iso8601'
+  changed:
+    properties:
+      - 'dc:modified'
+    datatype: 'xsd:dateTime'
+    datatype_callback: 'date_iso8601'
+  body:
+    properties:
+      - 'content:encoded'
+  uid:
+    properties:
+      - 'sioc:has_creator'
+    mapping_type: 'rel'
+  name:
+    properties:
+      - 'foaf:name'
+  comment_count:
+    properties:
+      - 'sioc:num_replies'
+    datatype: 'xsd:integer'
+  last_activity:
+    properties:
+      - 'sioc:last_activity_date'
+    datatype: 'xsd:dateTime'
+    datatype_callback: 'date_iso8601'
+  field_image:
+    properties:
+      - 'og:image'
+      - 'rdfs:seeAlso'
+    mapping_type: 'rel'
+  field_tags:
+    properties:
+      - 'dc:subject'
+    mapping_type: 'rel'
diff --git a/core/profiles/standard/config/rdf.mapping.node.page.yml b/core/profiles/standard/config/rdf.mapping.node.page.yml
new file mode 100644
index 0000000..b21ff4c
--- /dev/null
+++ b/core/profiles/standard/config/rdf.mapping.node.page.yml
@@ -0,0 +1,40 @@
+id: node.page
+targetEntityType: node
+bundle: page
+types:
+  - 'foaf:Document'
+  - 'sioc:Item'
+fieldMappings:
+  title:
+    properties:
+      - 'dc:title'
+  created:
+    properties:
+      - 'dc:date'
+      - 'dc:created'
+    datatype: 'xsd:dateTime'
+    datatype_callback: 'date_iso8601'
+  changed:
+    properties:
+      - 'dc:modified'
+    datatype: 'xsd:dateTime'
+    datatype_callback: 'date_iso8601'
+  body:
+    properties:
+      - 'content:encoded'
+  uid:
+    properties:
+      - 'sioc:has_creator'
+    mapping_type: 'rel'
+  name:
+    properties:
+      - 'foaf:name'
+  comment_count:
+    properties:
+      - 'sioc:num_replies'
+    datatype: 'xsd:integer'
+  last_activity:
+    properties:
+      - 'sioc:last_activity_date'
+    datatype: 'xsd:dateTime'
+    datatype_callback: 'date_iso8601'
diff --git a/core/profiles/standard/config/rdf.mapping.taxonomy_term.tags.yml b/core/profiles/standard/config/rdf.mapping.taxonomy_term.tags.yml
new file mode 100644
index 0000000..1069b58
--- /dev/null
+++ b/core/profiles/standard/config/rdf.mapping.taxonomy_term.tags.yml
@@ -0,0 +1,10 @@
+id: user.user
+targetEntityType: user
+bundle: user
+types:
+  - 'skos:Concept'
+fieldMappings:
+  name:
+    properties:
+      - 'rdfs:label'
+      - 'skos:prefLabel'
diff --git a/core/profiles/standard/config/rdf.mapping.user.user.yml b/core/profiles/standard/config/rdf.mapping.user.user.yml
new file mode 100644
index 0000000..aca7813
--- /dev/null
+++ b/core/profiles/standard/config/rdf.mapping.user.user.yml
@@ -0,0 +1,13 @@
+id: user.user
+targetEntityType: user
+bundle: user
+types:
+  - 'sioc:UserAccount'
+fieldMappings:
+  name:
+    properties:
+      - 'foaf:name'
+  homepage:
+    properties:
+      - 'foaf:page'
+    mapping_type: 'rel'
diff --git a/core/profiles/standard/standard.install b/core/profiles/standard/standard.install
index 741f857..7bae7df 100644
--- a/core/profiles/standard/standard.install
+++ b/core/profiles/standard/standard.install
@@ -54,34 +54,6 @@ function standard_install() {
     node_add_body_field($type);
   }
 
-  // Insert default pre-defined RDF mapping into the database.
-  $rdf_mappings = array(
-    array(
-      'type' => 'node',
-      'bundle' => 'page',
-      'mapping' => array(
-        'rdftype' => array('foaf:Document'),
-      ),
-    ),
-    array(
-      'type' => 'node',
-      'bundle' => 'article',
-      'mapping' => array(
-        'field_image' => array(
-          'predicates' => array('og:image', 'rdfs:seeAlso'),
-          'type' => 'rel',
-        ),
-        'field_tags' => array(
-          'predicates' => array('dc:subject'),
-          'type' => 'rel',
-        ),
-      ),
-    ),
-  );
-  foreach ($rdf_mappings as $rdf_mapping) {
-    rdf_mapping_save($rdf_mapping);
-  }
-
   // Default "Basic page" to not be promoted and have comments disabled.
   variable_set('node_options_page', array('status'));
   variable_set('comment_page', COMMENT_NODE_HIDDEN);
