diff --git a/addressfield.module b/addressfield.module
index 25b277d..e7ecb91 100644
--- a/addressfield.module
+++ b/addressfield.module
@@ -279,6 +279,26 @@ function _addressfield_render_address(&$format, $address) {
 }
 
 /**
+ * Helper function to get the field's properties' attributes array for use in
+ * format plugins. Returned array contains class and microdata attributes.
+ */
+function _addressfield_get_attributes($microdata = array()) {
+  $attributes = array();
+
+  foreach (array_keys(addressfield_data_property_info()) as $property) {
+    // If microdata is enabled, include the microdata attributes.
+    if (module_exists('microdata') && !empty($microdata[$property])) {
+      $attributes[$property] = $microdata[$property]['#attributes'];
+    }
+
+    // Add the class.
+    $attributes[$property]['class'] = array(str_replace('_', '-', $property));
+  }
+
+  return $attributes;
+}
+
+/**
  * @} End of "ingroup addressfield_format"
  */
 
@@ -353,6 +373,7 @@ function addressfield_field_info() {
     'default_formatter' => 'addressfield_default',
     'property_type' => 'addressfield',
     'property_callbacks' => array('addressfield_property_info_callback'),
+    'microdata' => TRUE,
   );
 
   return $fields;
@@ -750,6 +771,15 @@ function addressfield_field_formatter_view($entity_type, $entity, $field, $insta
   $settings = $display['settings'];
   $element = array();
 
+  // If the microdata module is enabled, get the microdata attributes from the
+  // entity variable. Otherwise, initialize an empty array.
+  if (module_exists('microdata') && isset($entity->microdata[$field['field_name']])) {
+    $microdata = $entity->microdata[$field['field_name']];
+  }
+  else {
+    $microdata = array();
+  }
+
   switch ($display['type']) {
     case 'addressfield_default':
       if (!empty($settings['use_widget_handlers'])) {
@@ -766,6 +796,7 @@ function addressfield_field_formatter_view($entity_type, $entity, $field, $insta
           'instance' => $instance,
           'langcode' => $langcode,
           'delta' => $delta,
+          'microdata' => $microdata,
         );
         $element[$delta] = addressfield_generate($address, $handlers, $context);
       }
@@ -857,6 +888,7 @@ function addressfield_data_property_info($name = NULL) {
       'type' => 'text',
       'getter callback' => 'entity_property_verbatim_get',
       'setter callback' => 'entity_property_verbatim_set',
+      'microdata' => TRUE,
     );
   }
 
@@ -864,6 +896,52 @@ function addressfield_data_property_info($name = NULL) {
 }
 
 /**
+ * Implements hook_microdata_value_types_alter().
+ */
+function addressfield_microdata_value_types_alter(&$types) {
+  $types['addressfield'] = 'item_option';
+}
+
+/**
+ * Implements hook_microdata_suggestions.
+ */
+function addressfield_microdata_suggestions() {
+  $suggestions = array();
+
+  $suggestions['fields']['addressfield']['schema.org'] = array(
+    '#itemprop'    => array('address'),
+    '#is_item' => TRUE,
+    '#itemtype'    => array('http://schema.org/PostalAddress'),
+    'name_line' => array(
+      '#itemprop' => array('name'),
+    ),
+    'organization_name' => array(
+      '#itemprop' => array('name'),
+    ),
+    'thoroughfare' => array(
+      '#itemprop' => array('streetAddress'),
+    ),
+    'premise' => array(
+      '#itemprop' => array('streetAddress'),
+    ),
+    'locality'  => array(
+      '#itemprop'    => array('addressLocality'),
+    ),
+    'administrative_area' => array(
+      '#itemprop'    => array('addressRegion'),
+    ),
+    'postal_code' => array(
+      '#itemprop' => array('postalCode'),
+    ),
+    'country'     => array(
+      '#itemprop'    => array('addressCountry'),
+    ),
+  );
+
+  return $suggestions;
+}
+
+/**
  * Returns the country list in a format suitable for use as an options list.
  */
 function _addressfield_country_options_list($field = NULL, $instance = NULL) {
diff --git a/plugins/format/address.inc b/plugins/format/address.inc
index e9b801f..3f43e99 100644
--- a/plugins/format/address.inc
+++ b/plugins/format/address.inc
@@ -25,6 +25,16 @@ function addressfield_format_address_generate(&$format, $address, $context = arr
   // Used to move certain fields to their own row.
   $clearfix = '<div class="clearfix"></div>';
 
+  // Get class and microdata attributes. If this is the form view,
+  // $context['microdata'] will not be set, so call without microdata to get
+  // the classes.
+  if (isset($context['microdata'])) {
+    $attributes = _addressfield_get_attributes($context['microdata']);
+  }
+  else {
+    $attributes = _addressfield_get_attributes();
+  }
+
   // The street block.
   $format['street_block'] = array(
     '#type' => 'addressfield_container',
@@ -33,24 +43,22 @@ function addressfield_format_address_generate(&$format, $address, $context = arr
     ),
     '#weight' => 0,
   );
+  $thoroughfare_array = $attributes['thoroughfare'];
+  $thoroughfare_array['autocomplete'] = 'address-line1';
   $format['street_block']['thoroughfare'] = array(
     '#title' => t('Address 1'),
     '#tag' => 'div',
-    '#attributes' => array(
-      'class' => array('thoroughfare'),
-      'autocomplete' => 'address-line1',
-    ),
+    '#attributes' => $thoroughfare_array,
     '#size' => 30,
     '#maxlength' => 255,
     '#required' => TRUE,
   );
+  $premise_array = $attributes['premise'];
+  $premise_array['autocomplete'] = 'address-line2';
   $format['street_block']['premise'] = array(
     '#title' => t('Address 2'),
     '#tag' => 'div',
-    '#attributes' => array(
-      'class' => array('premise'),
-      'autocomplete' => 'address-line2',
-    ),
+    '#attributes' => $premise_array,
     '#size' => 30,
     '#maxlength' => 255,
   );
@@ -63,16 +71,15 @@ function addressfield_format_address_generate(&$format, $address, $context = arr
     '#maxlength' => 255,
   );
   $format['locality_block']['#attached']['css'][] = drupal_get_path('module', 'addressfield') . '/addressfield.css';
+  $postal_code_array = $attributes['postal_code'];
+  $postal_code_array['autocomplete'] = 'postal_code';
   $format['locality_block']['postal_code'] = array(
     '#title' => $address_format['postal_code_label'],
     '#required' => in_array('postal_code', $address_format['required_fields']),
     '#access' => in_array('postal_code', $address_format['used_fields']),
     '#size' => 10,
     '#maxlength' => 255,
-    '#attributes' => array(
-      'class' => array('postal-code'),
-      'autocomplete' => 'postal-code',
-    ),
+    '#attributes' => $postal_code_array,
   );
   $format['locality_block']['dependent_locality'] = array(
     '#title' => $address_format['dependent_locality_label'],
@@ -88,6 +95,8 @@ function addressfield_format_address_generate(&$format, $address, $context = arr
     // Most formats place this field in its own row.
     '#suffix' => $clearfix,
   );
+  $locality_array = $attributes['locality'];
+  $locality_array['autocomplete'] = 'address-level2';
   $format['locality_block']['locality'] = array(
     '#title' => $address_format['locality_label'],
     '#required' => in_array('locality', $address_format['required_fields']),
@@ -95,11 +104,10 @@ function addressfield_format_address_generate(&$format, $address, $context = arr
     '#size' => 30,
     '#maxlength' => 255,
     '#prefix' => ' ',
-    '#attributes' => array(
-      'class' => array('locality'),
-      'autocomplete' => 'address-level2',
-    ),
+    '#attributes' => $locality_array,
   );
+  $administrative_area_array = $attributes['administrative_area'];
+  $administrative_area_array['autocomplete'] = 'address-level1';
   $format['locality_block']['administrative_area'] = array(
     '#title' => $address_format['administrative_area_label'],
     '#required' => in_array('administrative_area', $address_format['required_fields']),
@@ -109,20 +117,16 @@ function addressfield_format_address_generate(&$format, $address, $context = arr
     '#maxlength' => 255,
     '#prefix' => ' ',
     '#render_option_value' => $address_format['render_administrative_area_value'],
-    '#attributes' => array(
-      'class' => array('state'),
-      'autocomplete' => 'address-level1',
-    ),
+    '#attributes' => $administrative_area_array,
   );
+  $country_array = $attributes['country'];
+  $country_array['autocomplete'] = 'country';
   $format['country'] = array(
     '#title' => t('Country'),
     '#options' => _addressfield_country_options_list(),
     '#render_option_value' => TRUE,
     '#required' => TRUE,
-    '#attributes' => array(
-      'class' => array('country'),
-      'autocomplete' => 'country',
-    ),
+    '#attributes' => $country_array,
     '#weight' => 100,
   );
 
diff --git a/plugins/format/name-full.inc b/plugins/format/name-full.inc
index b9c6b22..8d0d3ce 100644
--- a/plugins/format/name-full.inc
+++ b/plugins/format/name-full.inc
@@ -17,7 +17,17 @@ $plugin = array(
  *
  * @see CALLBACK_addressfield_format_callback()
  */
-function addressfield_format_name_full_generate(&$format, $address) {
+function addressfield_format_name_full_generate(&$format, $address, $context = array()) {
+  // Get class and microdata attributes. If this is the form view,
+  // $context['microdata'] will not be set, so call without microdata to get
+  // the classes.
+  if (isset($context['microdata'])) {
+    $attributes = _addressfield_get_attributes($context['microdata']);
+  }
+  else {
+    $attributes = _addressfield_get_attributes();
+  }
+
   $format['name_block'] = array(
     '#type' => 'addressfield_container',
     '#attributes' => array(
@@ -30,25 +40,23 @@ function addressfield_format_name_full_generate(&$format, $address) {
   );
   // Maxlength is set to 127 so that the name_line still can be created without
   // exceeding the char limit from the database.
+  $first_name_array = $attributes['first_name'];
+  $first_name_array['autocomplete'] = 'given-name';
   $format['name_block']['first_name'] = array(
     '#title' => t('First name'),
     '#size' => 30,
     '#maxlength' => 127,
     '#required' => TRUE,
-    '#attributes' => array(
-      'class' => array('first-name'),
-      'autocomplete' => 'given-name',
-    ),
+    '#attributes' => $first_name_array,
   );
+  $last_name_array = $attributes['last_name'];
+  $last_name_array['autocomplete'] = 'family-name';
   $format['name_block']['last_name'] = array(
     '#title' => t('Last name'),
     '#size' => 30,
     '#maxlength' => 127,
     '#required' => TRUE,
     '#prefix' => ' ',
-    '#attributes' => array(
-      'class' => array('last-name'),
-      'autocomplete' => 'family-name',
-    ),
+    '#attributes' => $last_name_array,
   );
 }
diff --git a/plugins/format/name-oneline.inc b/plugins/format/name-oneline.inc
index cd6f726..69447cb 100644
--- a/plugins/format/name-oneline.inc
+++ b/plugins/format/name-oneline.inc
@@ -17,7 +17,17 @@ $plugin = array(
  *
  * @see CALLBACK_addressfield_format_callback()
  */
-function addressfield_format_name_oneline_generate(&$format, $address) {
+function addressfield_format_name_oneline_generate(&$format, $address, $context = array()) {
+  // Get class and microdata attributes. If this is the form view,
+  // $context['microdata'] will not be set, so call without microdata to get
+  // the classes.
+  if (isset($context['microdata'])) {
+    $attributes = _addressfield_get_attributes($context['microdata']);
+  }
+  else {
+    $attributes = _addressfield_get_attributes();
+  }
+
   $format['name_block'] = array(
     '#type' => 'addressfield_container',
     '#attributes' => array('class' => array('addressfield-container-inline', 'name-block')),
@@ -26,13 +36,12 @@ function addressfield_format_name_oneline_generate(&$format, $address) {
     // until one is selected.
     '#access' => !empty($address['country']),
   );
+  $name_line_array = $attributes['name_line'];
+  $name_line_array['autocomplete'] = 'name';
   $format['name_block']['name_line'] = array(
     '#title' => t('Full name'),
     '#tag' => 'div',
-    '#attributes' => array(
-      'class' => array('name-block'),
-      'autocomplete' => 'name',
-    ),
+    '#attributes' => $name_line_array,
     '#size' => 30,
     '#maxlength' => 255,
     '#required' => TRUE,
diff --git a/plugins/format/organisation.inc b/plugins/format/organisation.inc
index 3cec0f7..07b35ed 100644
--- a/plugins/format/organisation.inc
+++ b/plugins/format/organisation.inc
@@ -17,7 +17,17 @@ $plugin = array(
  *
  * @see CALLBACK_addressfield_format_callback()
  */
-function addressfield_format_organisation_generate(&$format, $address) {
+function addressfield_format_organisation_generate(&$format, $address, $context = array()) {
+  // Get class and microdata attributes. If this is the form view,
+  // $context['microdata'] will not be set, so call without microdata to get
+  // the classes.
+  if (isset($context['microdata'])) {
+    $attributes = _addressfield_get_attributes($context['microdata']);
+  }
+  else {
+    $attributes = _addressfield_get_attributes();
+  }
+
   $format['organisation_block'] = array(
     '#type' => 'addressfield_container',
     '#attributes' => array('class' => array('addressfield-container-inline', 'organisation-block')),
@@ -26,13 +36,12 @@ function addressfield_format_organisation_generate(&$format, $address) {
     // until one is selected.
     '#access' => !empty($address['country']),
   );
+  $organisation_name_array = $attributes['organisation_name'];
+  $organisation_name_array['autocomplete'] = 'organisation';
   $format['organisation_block']['organisation_name'] = array(
     '#title' => t('Company'),
     '#size' => 30,
     '#maxlength' => 255,
-    '#attributes' => array(
-      'class' => array('organisation-name'),
-      'autocomplete' => 'organization',
-    ),
+    '#attributes' => $organisation_name_array,
   );
 }
