diff --git a/core/lib/Drupal/Core/CoreBundle.php b/core/lib/Drupal/Core/CoreBundle.php
index 00e61dd..2076707 100644
--- a/core/lib/Drupal/Core/CoreBundle.php
+++ b/core/lib/Drupal/Core/CoreBundle.php
@@ -232,7 +232,6 @@ public function build(ContainerBuilder $container) {
     $container->register('serializer.normalizer.list', 'Drupal\Core\Serialization\ListNormalizer')->addTag('normalizer');
     $container->register('serializer.normalizer.typed_data', 'Drupal\Core\Serialization\TypedDataNormalizer')->addTag('normalizer');
     $container->register('serializer.encoder.json', 'Drupal\Core\Serialization\JsonEncoder')->addTag('encoder');
-    $container->register('serializer.encoder.xml', 'Drupal\Core\Serialization\XmlEncoder')->addTag('encoder');
 
     $container->register('flood', 'Drupal\Core\Flood\DatabaseBackend')
       ->addArgument(new Reference('database'));
diff --git a/core/lib/Drupal/Core/Serialization/XmlEncoder.php b/core/lib/Drupal/Core/Serialization/XmlEncoder.php
deleted file mode 100644
index 7235af3..0000000
--- a/core/lib/Drupal/Core/Serialization/XmlEncoder.php
+++ /dev/null
@@ -1,72 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Core\Serialization\XmlEncoder.
- */
-
-namespace Drupal\Core\Serialization;
-
-use Symfony\Component\Serializer\Encoder\EncoderInterface;
-use Symfony\Component\Serializer\Encoder\DecoderInterface;
-use Symfony\Component\Serializer\Encoder\SerializerAwareEncoder;
-use Symfony\Component\Serializer\Encoder\XmlEncoder as BaseXmlEncoder;
-
-/**
- * Adds XML support for serializer.
- *
- * This acts as a wrapper class for Symfony's XmlEncoder so that it is not
- * implementing NormalizationAwareInterface, and can be normalized externally.
- */
-class XmlEncoder extends SerializerAwareEncoder implements EncoderInterface, DecoderInterface {
-
-  /**
-   * The formats that this Encoder supports.
-   *
-   * @var array
-   */
-  static protected $format = array('xml');
-
-  /**
-   * An instance of the Symfony XmlEncoder to perform the actual encoding.
-   *
-   * @var \Symfony\Component\Serializer\Encoder\XmlEncoder
-   */
-  protected $baseEncoder;
-
-  /**
-   * Constucts the XmlEncoder object, creating a BaseXmlEncoder class also.
-   */
-  public function __construct() {
-    $this->baseEncoder = new BaseXmlEncoder();
-  }
-
-  /**
-   * Implements \Symfony\Component\Serializer\Encoder\EncoderInterface::encode().
-   */
-  public function encode($data, $format){
-    $normalized = $this->serializer->normalize($data, $format);
-    return $this->baseEncoder->encode($normalized, $format);
-  }
-
-  /**
-   * Implements \Symfony\Component\Serializer\Encoder\JsonEncoder::supportsEncoding().
-   */
-  public function supportsEncoding($format) {
-    return in_array($format, static::$format);
-  }
-
-  /**
-   * Implements \Symfony\Component\Serializer\Encoder\EncoderInterface::decode().
-   */
-  public function decode($data, $format){
-    return $this->baseEncoder->decode($data, $format);
-  }
-
-  /**
-   * Implements \Symfony\Component\Serializer\Encoder\JsonEncoder::supportsDecoding().
-   */
-  public function supportsDecoding($format) {
-    return in_array($format, static::$format);
-  }
-}
diff --git a/core/modules/edit/edit.module b/core/modules/edit/edit.module
index a704221..60f845d 100644
--- a/core/modules/edit/edit.module
+++ b/core/modules/edit/edit.module
@@ -164,7 +164,9 @@ function edit_library_info() {
 function edit_preprocess_field(&$variables) {
   $element = $variables['element'];
   $entity = $element['#object'];
-  $variables['attributes']['data-edit-id'] = $entity->entityType() . '/' . $entity->id() . '/' . $element['#field_name'] . '/' . $element['#language'] . '/' . $element['#view_mode'];
+  if (empty($entity->in_preview)) {
+    $variables['attributes']['data-edit-id'] = $entity->entityType() . '/' . $entity->id() . '/' . $element['#field_name'] . '/' . $element['#language'] . '/' . $element['#view_mode'];
+  }
 }
 
 /**
diff --git a/core/modules/node/lib/Drupal/node/NodeFormController.php b/core/modules/node/lib/Drupal/node/NodeFormController.php
index 47e1f30..15df858 100644
--- a/core/modules/node/lib/Drupal/node/NodeFormController.php
+++ b/core/modules/node/lib/Drupal/node/NodeFormController.php
@@ -26,6 +26,18 @@ class NodeFormController extends EntityFormController {
    * Overrides Drupal\Core\Entity\EntityFormController::prepareEntity().
    */
   protected function prepareEntity(EntityInterface $node) {
+
+    // @todo decide how to get a fresh one.
+    // @todo the actual node is override in ::form as trying
+    // to overide here doesn't work.
+    $tempstore_id = drupal_container()->get('request')->query->get('tempstore_id');
+    if ($tempstore_id) {
+      $node->tempstore_id = $tempstore_id;
+    }
+    else {
+      $node->tempstore_id = $node->uuid;
+    }
+
     // Set up default values, if required.
     $node_options = variable_get('node_options_' . $node->type, array('status', 'promote'));
     // If this is a new node, fill in the default values.
@@ -71,13 +83,16 @@ public function form(array $form, array &$form_state, EntityInterface $node) {
     }
 
     $user_config = config('user.settings');
-    // Some special stuff when previewing a node.
-    if (isset($form_state['node_preview'])) {
-      $form['#prefix'] = $form_state['node_preview'];
-      $node->in_preview = TRUE;
-    }
-    else {
-      unset($node->in_preview);
+
+    // @todo can we do this somewhere different ?
+    $tempstore_id = drupal_container()->get('request')->query->get('tempstore_id');
+    if (!empty($tempstore_id) && ($data = node_tempstore_load($tempstore_id))) {
+      $node = $data;
+
+      // We have to prepare the node to fix the autocomplete tags widget.
+      // @todo now we do a double prepare... Is that allowed? Probably not...
+      node_invoke($node, 'prepare');
+      module_invoke_all('node_prepare', $node);
     }
 
     // Override the default CSS class name, since the user-defined node type
@@ -381,9 +396,10 @@ public function submit(array $form, array &$form_state) {
    *   A reference to a keyed array containing the current state of the form.
    */
   public function preview(array $form, array &$form_state) {
-    drupal_set_title(t('Preview'), PASS_THROUGH);
-    $form_state['node_preview'] = node_preview($this->getEntity($form_state));
-    $form_state['rebuild'] = TRUE;
+    $entity = $this->getEntity($form_state);
+    $entity->in_preview = TRUE;
+    drupal_container()->get('user.tempstore')->get('node')->set($entity->tempstore_id, $entity);
+    $form_state['redirect'] = 'node/preview/' . $entity->tempstore_id;
   }
 
   /**
@@ -418,6 +434,9 @@ public function save(array $form, array &$form_state) {
       $form_state['rebuild'] = TRUE;
     }
 
+    // Remove from cache.
+    drupal_container()->get('user.tempstore')->get('node')->delete($node->tempstore_id);
+
     // Clear the page and block caches.
     cache_invalidate_tags(array('content' => TRUE));
   }
diff --git a/core/modules/node/lib/Drupal/node/Plugin/Core/Entity/Node.php b/core/modules/node/lib/Drupal/node/Plugin/Core/Entity/Node.php
index 6cf9fac..660c9fe 100644
--- a/core/modules/node/lib/Drupal/node/Plugin/Core/Entity/Node.php
+++ b/core/modules/node/lib/Drupal/node/Plugin/Core/Entity/Node.php
@@ -206,6 +206,13 @@ class Node extends Entity implements ContentEntityInterface {
   public $revision_uid;
 
   /**
+   * The node tempstore id.
+   *
+   * @var integer
+   */
+  public $tempstore_id;
+
+  /**
    * Implements Drupal\Core\Entity\EntityInterface::id().
    */
   public function id() {
diff --git a/core/modules/node/node.module b/core/modules/node/node.module
index eb56876..625e6c3 100644
--- a/core/modules/node/node.module
+++ b/core/modules/node/node.module
@@ -158,10 +158,6 @@ function node_theme() {
       'variables' => array('content' => NULL),
       'file' => 'node.pages.inc',
     ),
-    'node_preview' => array(
-      'variables' => array('node' => NULL),
-      'file' => 'node.pages.inc',
-    ),
     'node_admin_overview' => array(
       'variables' => array('name' => NULL, 'type' => NULL),
     ),
@@ -943,6 +939,23 @@ function node_load($nid = NULL, $reset = FALSE) {
 }
 
 /**
+ * Load the node from the tempstore.
+ *
+ * @param int $tempstore_id
+ *   The id of a tempstore object.
+ *
+ * @return Drupal\node\Node|false
+ *   A fully-populated node entity, or FALSE if the node is not found.
+ */
+function node_tempstore_load($tempstore_id) {
+  $node = drupal_container()->get('user.tempstore')->get('node')->get($tempstore_id);
+  if ($node) {
+    return $node;
+  }
+  return FALSE;
+}
+
+/**
  * Loads a node revision from the database.
  *
  * @param int $nid
@@ -1740,6 +1753,13 @@ function node_menu() {
     'type' => MENU_DEFAULT_LOCAL_TASK,
     'weight' => -10,
   );
+  // @todo real access check.
+  $items['node/preview/%node_tempstore'] = array(
+    'page callback' => 'node_preview',
+    'page arguments' => array(2),
+    'access callback' => TRUE,
+    'file' => 'node.pages.inc',
+  );
   $items['node/%node/edit'] = array(
     'title' => 'Edit',
     'page callback' => 'node_page_edit',
@@ -2256,6 +2276,98 @@ function node_page_view(Node $node) {
 }
 
 /**
+ * Implements hook_page_build().
+ */
+function node_page_build(&$page) {
+
+  // Add 'Back to content edit editing' link on preview page.
+  $node = menu_get_object('node_tempstore', 2);
+  if ($node) {
+
+    $page['page_top']['node-preview'] = array(
+      '#type' => 'container',
+      '#attributes' => array(
+        'class' => array('node-preview-container', 'container-inline')
+      ),
+    );
+
+    $form = drupal_get_form('node_preview_form_select', $node);
+    $page['page_top']['node-preview']['view-mode'] = $form;
+  }
+}
+
+/**
+ * Get the preview form selection box.
+ *
+ * @param string $bundle
+ *   The name of the node bundle.
+ *
+ * @return $form
+ *   The view mode preview selection form.
+ */
+function node_preview_form_select($form, $form_state, $node) {
+
+  // Always add default.
+  $view_mode_options = array('default' => t('Full'));
+
+  // Get view mode options.
+  $entity_info = entity_get_info('node');
+  foreach ($entity_info['view_modes'] as $key => $info) {
+    if (!empty($info['custom_settings'])) {
+      $view_mode_options[$key] = $info['label'];
+    }
+  }
+
+  $link = 'node/add/' . $node->bundle();
+  if (!empty($node->nid)) {
+    $link = 'node/' . $node->nid . '/edit';
+  }
+
+  $view_mode = drupal_container()->get('request')->query->get('view_mode');
+  if (empty($view_mode)) {
+    $view_mode = 'full';
+  }
+
+  $form['backlink'] = array(
+    '#type' => 'link',
+    '#title' => t('Back to content editing'),
+    '#href' => $link,
+    // Add the "overlay-restore" class to indicate this link should restore
+    // the context in which the preview demonstration page was opened.
+    '#options' => array('query' => array('tempstore_id' => $node->tempstore_id) ,'attributes' => array('class' => array('node-preview-backlink button-action', 'overlay-restore'))),
+    //'#prefix' => '<div class="node-preview-backlink-container">',
+    //'#suffix' => '</div>'
+  );
+
+  $form['tempstore_id'] = array(
+    '#type' => 'value',
+    '#value' => $node->tempstore_id
+  );
+
+  $form['view_mode'] = array(
+    '#type' => 'select',
+    '#options' => $view_mode_options,
+    '#default_value' => $view_mode,
+  );
+  $form['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Switch'),
+    '#attributes' => array(
+      'class' => array('node-preview-switch-button')
+    )
+  );
+
+  return $form;
+}
+
+/**
+ * Submit handler for the node preview select form.
+ */
+function node_preview_form_select_submit($form, &$form_state) {
+  $form_state['redirect'] = array('node/preview/' . $form_state['values']['tempstore_id'], array('query' => array('view_mode' => $form_state['values']['view_mode'])));
+}
+
+/**
  * Implements hook_update_index().
  */
 function node_update_index() {
@@ -3673,6 +3785,9 @@ function node_library_info() {
     'js' => array(
       drupal_get_path('module', 'node') . '/node.preview.js' => array(),
     ),
+    'css' => array(
+      drupal_get_path('module', 'node') . '/node.preview.css' => array(),
+    ),
     'dependencies' => array(
       array('system', 'jquery'),
       array('system', 'drupal'),
diff --git a/core/modules/node/node.pages.inc b/core/modules/node/node.pages.inc
index 245fef7..f43234b 100644
--- a/core/modules/node/node.pages.inc
+++ b/core/modules/node/node.pages.inc
@@ -121,11 +121,17 @@ function node_add($node_type) {
  *
  * @return
  *   An HTML-formatted string of a node preview.
- *
- * @see node_form_build_preview()
  */
 function node_preview(Node $node) {
+
+  // @todo move access check earlier ?
   if (node_access('create', $node) || node_access('update', $node)) {
+
+    dpm($node);
+
+    // Set status to true so we don't get the 'unpublished' css.
+    $node->status = TRUE;
+
     _field_invoke_multiple('load', 'node', array($node->nid => $node));
     // Load the user's name when needed.
     if (isset($node->name)) {
@@ -145,56 +151,21 @@ function node_preview(Node $node) {
 
     $node->changed = REQUEST_TIME;
 
-    // Display a preview of the node.
-    if (!form_get_errors()) {
-      $node->in_preview = TRUE;
-      $output = theme('node_preview', array('node' => $node));
-      unset($node->in_preview);
+    // Get the view mode to render the preview in.
+    $view_mode = drupal_container()->get('request')->query->get('view_mode');
+    if (empty($view_mode)) {
+      $view_mode = 'full';
     }
 
-    return $output;
+    $build = array();
+    // @todo all links should be disabled, except for returning to the edit form.
+    $build['#attached']['library'][] = array('node', 'drupal.node.preview');
+    $build['preview'] = node_view($node, $view_mode);
+    return $build;
   }
 }
 
 /**
- * Returns HTML for a node preview for display during node creation and editing.
- *
- * @param $variables
- *   An associative array containing:
- *   - node: The node entity which is being previewed.
- *
- * @see NodeFormController::preview()
- * @see node_preview()
- *
- * @ingroup themeable
- */
-function theme_node_preview($variables) {
-  $node = $variables['node'];
-
-  $output = '';
-
-  $elements = node_view($node, 'teaser');
-  $elements['#attached']['library'][] = array('node', 'drupal.node.preview');
-  $trimmed = drupal_render($elements);
-  $elements = node_view($node, 'full');
-  $full = drupal_render($elements);
-
-  // Do we need to preview trimmed version of post as well as full version?
-  if ($trimmed != $full) {
-    drupal_set_message(t('The trimmed version of your post shows what your post looks like when promoted to the main page or when exported for syndication.<span class="no-js"> You can insert the delimiter "&lt;!--break--&gt;" (without the quotes) to fine-tune where your post gets split.</span>'));
-    $output .= '<h3>' . t('Preview trimmed version') . '</h3>';
-    $output .= $trimmed;
-    $output .= '<h3>' . t('Preview full version') . '</h3>';
-    $output .= $full;
-  }
-  else {
-    $output .= $full;
-  }
-
-  return $output;
-}
-
-/**
  * Page callback: Form constructor for node deletion confirmation form.
  *
  * @param object $node
diff --git a/core/modules/node/node.preview.css b/core/modules/node/node.preview.css
new file mode 100644
index 0000000..1b9270a
--- /dev/null
+++ b/core/modules/node/node.preview.css
@@ -0,0 +1,47 @@
+
+.node-preview-container {
+  background-color: #cee5f3;
+  position: fixed;
+  z-index: 499;
+  width: 100%;
+  padding: 10px;
+}
+
+.button-action {
+  background: #1078d4;
+  background-image: -webkit-linear-gradient(top, #419ff1, #1076d5);
+  background-image: -moz-linear-gradient(top, #419ff1, #1076d5);
+  background-image: -o-linear-gradient(top, #419ff1, #1076d5);
+  background-image: linear-gradient(to bottom, #419ff1, #1076d5);
+  border: 1px solid #0048c8;
+  border-radius: .4em;
+  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .4);
+  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .4);
+  color: #fff;
+  font-size: 1em;
+  line-height: normal;
+  margin: 0;
+  padding: 4px 1em;
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.5);
+}
+.button-action:focus,
+.button-action:hover {
+  background-color: #419cf1;
+  background-image: -webkit-linear-gradient(top, #59abf3, #2a90ef);
+  background-image: -moz-linear-gradient(top, #59abf3, #2a90ef);
+  background-image: -o-linear-gradient(top, #59abf3, #2a90ef);
+  background-image: linear-gradient(to bottom, #59abf3, #2a90ef);
+  border: 1px solid #0048c8;
+  color: #fff;
+}
+.button-action:active {
+  background-color: #0e69be;
+  background-image: -webkit-linear-gradient(top, #0e69be, #2a93ef);
+  background-image: -moz-linear-gradient(top, #0e69be, #2a93ef);
+  background-image: -o-linear-gradient(top, #0e69be, #2a93ef);
+  background-image: -ms-linear-gradient(top, #0e69be, #2a93ef);
+  background-image: linear-gradient(to bottom, #0e69be, #2a93ef);
+  border: 1px solid #0048c8;
+  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, .25);
+  box-shadow: inset 0 1px 2px rgba(0, 0, 0, .25);
+}
diff --git a/core/modules/node/node.preview.js b/core/modules/node/node.preview.js
index 3be74e2..be0f0cb 100644
--- a/core/modules/node/node.preview.js
+++ b/core/modules/node/node.preview.js
@@ -25,4 +25,16 @@ Drupal.behaviors.nodePreviewDestroyLinks = {
   }
 };
 
+/**
+ * View mode preview select form.
+ */
+Drupal.behaviors.nodePreviewSelectForm = {
+  attach: function (context) {
+    $('.node-preview-switch-button').hide();
+    $('#edit-view-mode').change(function() {
+      $(this).closest('form').trigger('submit');
+    });
+  }
+};
+
 })(jQuery, Drupal);
diff --git a/core/modules/system/lib/Drupal/system/Tests/Serialization/EntitySerializationTest.php b/core/modules/system/lib/Drupal/system/Tests/Serialization/EntitySerializationTest.php
index 5fb3c46..ea3c960 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Serialization/EntitySerializationTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Serialization/EntitySerializationTest.php
@@ -10,7 +10,6 @@
 use Drupal\simpletest\WebTestBase;
 use Symfony\Component\Serializer\Serializer;
 use Drupal\Core\Serialization\JsonEncoder;
-use Symfony\Component\Serializer\Encoder\XmlEncoder as BaseXmlEncoder;
 use Drupal\Core\Serialization\ComplexDataNormalizer;
 use Drupal\Core\Serialization\TypedDataNormalizer;
 
@@ -121,21 +120,9 @@ public function testSerialize() {
     $expected = json_encode($normalized);
     // Test 'json'.
     $actual = $serializer->serialize($this->entity, 'json');
-    $this->assertIdentical($actual, $expected, 'Entity serializes to JSON when "json" is requested.');
-    $actual = $serializer->serialize($normalized, 'json');
-    $this->assertIdentical($actual, $expected, 'A normalized array serializes to JSON when "json" is requested');
+    $this->assertIdentical($actual, $expected, 'Entity serializes to JSON when json is requested.');
     // Test 'ajax'.
     $actual = $serializer->serialize($this->entity, 'ajax');
-    $this->assertIdentical($actual, $expected, 'Entity serializes to JSON when "ajax" is requested.');
-    $actual = $serializer->serialize($normalized, 'ajax');
-    $this->assertIdentical($actual, $expected, 'A normalized array serializes to JSON when "ajax" is requested');
-    // Test 'xml'. The expected output should match that of Symfony's XmlEncoder.
-    $expected ='<?xml version="1.0"?>
-<response><id><value>1</value></id><revision_id><value>1</value></revision_id><uuid><value>' . $this->entity->uuid() . '</value></uuid><langcode><value>und</value></langcode><default_langcode><value/></default_langcode><name><value>' . $this->values['name'] . '</value></name><user_id><value>1</value></user_id><field_test_text><value>' . $this->values['field_test_text']['value'] . '</value><format>full_html</format></field_test_text></response>
-';
-    $actual = $serializer->serialize($this->entity, 'xml');
-    $this->assertIdentical($actual, $expected, 'Entity serializes to XML when "xml" is requested.');
-    $actual = $serializer->serialize($normalized, 'xml');
-    $this->assertIdentical($actual, $expected, 'A normalized array serializes to XML when "xml" is requested');
+    $this->assertIdentical($actual, $expected, 'Entity serializes to JSON when ajax is requested.');
   }
 }
