diff --git link.inc link.inc
index f702751..99c0c85 100644
--- link.inc
+++ link.inc
@@ -133,10 +133,26 @@ function _link_sanitize(&$item, $delta, &$field, &$node) {
   }
   $item['display_title'] = empty($title) ? $item['display_url'] : $title;
 
+  _link_sanitize_attributes($item, $field, $node, $type);
+}
+
+/**
+ * Sanitize a link field's attributes.
+ */
+function _link_sanitize_attributes(&$item, $field, $node, $type = NULL) {
   if (!isset($item['attributes'])) {
     $item['attributes'] = array();
   }
 
+  if (!isset($type)) {
+    $type = link_validate_url($item['url']);
+    // If we can't determine the type of url, and we've been told not to validate it,
+    // then we assume it's a LINK_EXTERNAL type for later processing. #357604
+    if ($type == FALSE && $field['validate_url'] === 0) {
+      $type = LINK_EXTERNAL;
+    }
+  }
+
   // Unserialize attributtes array if it has not been unserialized yet.
   if (!is_array($item['attributes'])) {
     $item['attributes'] = (array)unserialize($item['attributes']);
diff --git link.module link.module
index 4098ae0..62111f6 100644
--- link.module
+++ link.module
@@ -180,9 +180,9 @@ function link_field_settings($op, $field) {
 
     case 'database columns':
       return array(
-        'url' => array('type' => 'varchar', 'length' => LINK_URL_MAX_LENGTH, 'not null' => FALSE, 'sortable' => TRUE),
+        'url' => array('type' => 'varchar', 'length' => LINK_URL_MAX_LENGTH, 'not null' => FALSE, 'sortable' => TRUE, 'views' => TRUE),
         'title' => array('type' => 'varchar', 'length' => 255, 'not null' => FALSE, 'sortable' => TRUE),
-        'attributes' => array('type' => 'text', 'size' => 'medium', 'not null' => FALSE),
+        'attributes' => array('type' => 'text', 'size' => 'medium', 'not null' => FALSE, 'views' => TRUE),
       );
 
     case 'views data':
@@ -449,3 +449,24 @@ function link_views_api() {
     'path' => drupal_get_path('module', 'link') .'/views',
   );
 }
+
+
+/**
+ * Get a list of possible attributes stored in a link field "attributes" column.
+ */
+function link_attributes_info() {
+  return array(
+    'title' => array(
+      'title' => t('Title'),
+      'key' => 'title',
+    ),
+    'rel' => array(
+      'title' => t('Rel'),
+      'key' => 'rel',
+    ),
+    'target' => array(
+      'title' => t('Target'),
+      'key' => 'target',
+    ),
+  );
+}
diff --git views/link.views.inc views/link.views.inc
index 9f32b8a..a56a3fc 100644
--- views/link.views.inc
+++ views/link.views.inc
@@ -13,6 +13,9 @@ function link_views_handlers() {
       'path' => drupal_get_path('module', 'link') .'/views',
     ),
     'handlers' => array(
+      'link_views_handler_field_attributes' => array(
+        'parent' => 'views_handler_field_node',
+      ),
       'link_views_handler_argument_target' => array(
         'parent' => 'views_handler_argument',
       ),
@@ -73,6 +76,19 @@ function link_views_content_field_data($field) {
     ),
   );
 
+  // Add special handler for serialized attributes.
+  $data[$table_alias][$field['field_name'] .'_attributes']['field'] = array(
+    'title' => $data[$table_alias][$field['field_name'] .'_attributes']['title'],
+    'title short' => $data[$table_alias][$field['field_name'] .'_attributes']['title short'],
+    'help' => t('Can be used to display specific alt, title, or description information. May cause duplicate rows if grouping fields.'),
+    'field' => $db_info['columns']['data']['column'],
+    'table' => $db_info['table'],
+    'handler' => 'link_views_handler_field_attributes',
+    'click sortable' => FALSE,
+    'access callback' => 'content_access',
+    'access arguments' => array('view', $field),
+  );
+
   // Build out additional Views filter for the link "protocol" pseudo field.
   $data[$table_alias][$field['field_name'] .'_protocol'] = array(
     'group' => t('Content'),
diff --git views/link_views_handler_field_attributes.inc views/link_views_handler_field_attributes.inc
new file mode 100644
index 0000000..1843cfb
--- /dev/null
+++ views/link_views_handler_field_attributes.inc
@@ -0,0 +1,61 @@
+<?php
+
+/**
+ * @file
+ * link_views_handler_field_attributes.inc
+ *
+ * Provides a handler for displaying values within the serialized data column.
+ */
+class link_views_handler_field_attributes extends views_handler_field_node {
+
+  function option_definition() {
+    $options = parent::option_definition();
+    $options['attribute_name'] = array('default' => 'title');
+    return $options;
+  }
+
+  function options_form(&$form, &$form_state) {
+    parent::options_form($form, $form_state);
+
+    $attrs = link_attributes_info();
+    $options = array();
+    foreach ($attrs as $key => $attr) {
+      $options[$key] = $attr['title'];
+    }
+
+    $form['attribute_name'] = array(
+      '#title' => t('Attribute name'),
+      '#type' => 'radios',
+      '#options' => $options,
+      '#required' => TRUE,
+      '#default_value' => $this->options['attribute_name'],
+      '#description' => t('The name of the HTML attribute value to get.'),
+      '#weight' => 4,
+    );
+  }
+
+  function admin_summary() {
+    // Display the attribute name to be displayed.
+    $attrs = link_attributes_info();
+    return $attrs[$this->options['attribute_name']]['title'];
+  }
+
+  function render($values) {
+    $values = drupal_clone($values); // Prevent affecting the original.
+    static $fields;
+    if (!$fields[$values->node_type]) {
+      // drupal°substr(x, 0, -11) is used to remove '_attributes' at the end.
+      $fields[$values->node_type] = content_fields(drupal_substr($this->field, 0, -11), $values->node_type);
+    }
+    $node->nid = $values->nid;
+
+    $item = array('attributes' => $values->{$this->field_alias});
+
+    module_load_include('inc', 'link');
+    _link_sanitize_attributes($item, $fields[$values->node_type], $node);
+
+    $attrs = link_attributes_info();
+    return $item['attributes'][$attrs[$this->options['attribute_name']]['key']];
+  }
+
+}
