diff --git a/core/composer.lock b/core/composer.lock
index fe5dc0a..80e6fd3 100644
--- a/core/composer.lock
+++ b/core/composer.lock
@@ -729,6 +729,71 @@
             "time": "2014-10-12 19:18:40"
         },
         {
+            "name": "masterminds/html5",
+            "version": "dev-master",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/Masterminds/html5-php.git",
+                "reference": "398ebb68c9395a67858d230d0610aa3676bebdc7"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/398ebb68c9395a67858d230d0610aa3676bebdc7",
+                "reference": "398ebb68c9395a67858d230d0610aa3676bebdc7",
+                "shasum": ""
+            },
+            "require": {
+                "ext-libxml": "*",
+                "php": ">=5.3.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "4.*",
+                "sami/sami": "~2.0",
+                "satooshi/php-coveralls": "0.6.*"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.0-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Masterminds\\": "src"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Matt Butcher",
+                    "email": "technosophos@gmail.com"
+                },
+                {
+                    "name": "Asmir Mustafic",
+                    "email": "goetas@gmail.com"
+                },
+                {
+                    "name": "Matt Farina",
+                    "email": "matt@mattfarina.com"
+                }
+            ],
+            "description": "An HTML5 parser and serializer.",
+            "homepage": "http://masterminds.github.io/html5-php",
+            "keywords": [
+                "HTML5",
+                "dom",
+                "html",
+                "parser",
+                "querypath",
+                "serializer",
+                "xml"
+            ],
+            "time": "2014-12-02 02:51:14"
+        },
+        {
             "name": "mikey179/vfsStream",
             "version": "v1.4.0",
             "source": {
@@ -2594,7 +2659,8 @@
     "minimum-stability": "stable",
     "stability-flags": {
         "doctrine/common": 20,
-        "phpunit/phpunit-mock-objects": 20
+        "phpunit/phpunit-mock-objects": 20,
+        "masterminds/html5": 20
     },
     "prefer-stable": false,
     "prefer-lowest": false,
diff --git a/core/lib/Drupal/Component/Utility/Html.php b/core/lib/Drupal/Component/Utility/Html.php
index 4dd9d27..e492bf4 100644
--- a/core/lib/Drupal/Component/Utility/Html.php
+++ b/core/lib/Drupal/Component/Utility/Html.php
@@ -7,6 +7,8 @@
 
 namespace Drupal\Component\Utility;
 
+use Masterminds\HTML5;
+
 /**
  * Provides DOMDocument helpers for parsing and serializing HTML strings.
  *
@@ -272,9 +274,9 @@ public static function normalize($html) {
    */
   public static function load($html) {
     $document = <<<EOD
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head>
+<!DOCTYPE html>
+<html>
+<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head>
 <body>!html</body>
 </html>
 EOD;
@@ -283,9 +285,8 @@ public static function load($html) {
     // newlines before injecting the actual HTML body to process.
     $document = strtr($document, array("\n" => '', '!html' => $html));
 
-    $dom = new \DOMDocument();
-    // Ignore warnings during HTML soup loading.
-    @$dom->loadHTML($document);
+    $html5 = new HTML5();
+    $dom = $html5->loadHTML($document);
 
     return $dom;
   }
@@ -314,8 +315,9 @@ public static function serialize(\DOMDocument $document) {
     foreach ($body_node->getElementsByTagName('style') as $node) {
       static::escapeCdataElement($node, '/*', '*/');
     }
+    $html5 = new HTML5();
     foreach ($body_node->childNodes as $node) {
-      $html .= $document->saveXML($node);
+      $html .= $html5->saveHTML($node);
     }
     return $html;
   }
diff --git a/core/lib/Drupal/Component/XpathHelper/Lexer.php b/core/lib/Drupal/Component/XpathHelper/Lexer.php
new file mode 100644
index 0000000..8876aac
--- /dev/null
+++ b/core/lib/Drupal/Component/XpathHelper/Lexer.php
@@ -0,0 +1,240 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Component\XpathHelper\Lexer.
+ */
+
+namespace Drupal\Component\XpathHelper;
+
+/**
+ * Turns an XPath expression into a list of tokens.
+ */
+class Lexer {
+
+  /**
+   * The XPath expression being lexed.
+   *
+   * @var string
+   */
+  protected $expression;
+
+  /**
+   * The current position in the expression.
+   *
+   * @var int
+   */
+  protected $cursor;
+
+  /**
+   * The length of the XPath expression.
+   *
+   * @var int
+   */
+  protected $length;
+
+  /**
+   * Characters that represent word boundaries.
+   *
+   * @var array
+   */
+  protected static $wordBoundaries = array(
+    '[' => TRUE,
+    ']' => TRUE,
+    '=' => TRUE,
+    '(' => TRUE,
+    ')' => TRUE,
+    '.' => TRUE,
+    '<' => TRUE,
+    '>' => TRUE,
+    '*' => TRUE,
+    '+' => TRUE,
+    // Used in element names and functions. It's easier to just make a special
+    // case in the parser than to have the minus be a word boundary.
+    // '-' => TRUE,
+    '!' => TRUE,
+    '|' => TRUE,
+    ',' => TRUE,
+    ' ' => TRUE,
+    '"' => TRUE,
+    "'" => TRUE,
+    ':' => TRUE,
+    '::' => TRUE,
+    '/' => TRUE,
+    '//' => TRUE,
+    '@' => TRUE,
+  );
+
+  /**
+   * Lexes an XPath expression.
+   *
+   * @param string $expression
+   *   An XPath expression.
+   *
+   * @return array
+   *   A list of tokens from the XPath expression.
+   */
+  public function lex($expression) {
+    $this->expression = $expression;
+    $this->length = strlen($expression);
+    $this->cursor = 0;
+
+    $tokens = array();
+    while (TRUE) {
+      $token = $this->readToken();
+      if ($token === '') {
+        break;
+      }
+      $tokens[] = $token;
+    }
+
+    return $tokens;
+  }
+
+  /**
+   * Determines if a token is boundary for a word.
+   *
+   * @param string $token
+   *   The token.
+   *
+   * @return bool
+   *   Returns true if the token is a word boundary, and false if not.
+   */
+  public static function isWordBoundary($token) {
+    return isset(static::$wordBoundaries[$token]);
+  }
+
+  /**
+   * Reads the next token from the expression.
+   *
+   * @return string
+   *   The next token, or an empty string on completion.
+   */
+  protected function readToken() {
+    while ($this->cursor < $this->length) {
+      $char = $this->expression[$this->cursor];
+
+      if ($char === '/') {
+        return $this->readOneOrTwoSlashes($char);
+      }
+
+      if ($char === '"' || $char === "'") {
+        return $this->consumeQuotes($char);
+      }
+
+      if ($char === ':') {
+        return $this->readNamespaceOrAxis();
+      }
+
+      if ($char === '@') {
+        return $this->readAttribute();
+      }
+
+      if ($this->isWordBoundary($char)) {
+        $this->cursor++;
+        return $char;
+      }
+
+      return $this->readWord();
+    }
+
+    return '';
+  }
+
+  /**
+   * Reads the next word from the expression.
+   *
+   * A word is considered anything that isn't a word boundary.
+   *
+   * @return string
+   *   The next word.
+   */
+  protected function readWord() {
+    $word = '';
+
+    while ($this->cursor < $this->length) {
+      $char = $this->expression[$this->cursor];
+
+      // Found a boundary.
+      if ($this->isWordBoundary($char)) {
+        break;
+      }
+
+      $word .= $char;
+      $this->cursor++;
+    }
+
+    return $word;
+  }
+
+  /**
+   * Reads a quoted string from an XPath expression.
+   *
+   * @param string $start_quote
+   *   The character that started the quoted string.
+   *
+   * @return string
+   *   The quoted string.
+   */
+  protected function consumeQuotes($start_quote) {
+    $output = $start_quote;
+    do {
+      $next_char = $this->readNextChar();
+      $output .= $next_char;
+    } while ($next_char !== '' && $next_char !== $start_quote);
+
+    $this->cursor++;
+    return $output;
+  }
+
+  /**
+   * Reads a namespace token or an axis token.
+   *
+   * @return string
+   *   Either a namespace separator or an axis separator. One or two colons.
+   */
+  protected function readNamespaceOrAxis() {
+    if ($this->readNextChar() === ':') {
+      $this->cursor++;
+      return '::';
+    }
+    return ':';
+  }
+
+  /**
+   * Reads on or two slashes.
+   *
+   * @return string
+   *  Returns / or //.
+   */
+  protected function readOneOrTwoSlashes() {
+    if ($this->readNextChar() === '/') {
+      $this->cursor++;
+      return '//';
+    }
+    return '/';
+  }
+
+  /**
+   * Reads a shorthand attribute.
+   *
+   * @return string
+   *   An attribute string starting with @.
+   */
+  protected function readAttribute() {
+    $this->cursor++;
+    return '@' . $this->readWord();
+  }
+
+  /**
+   * Returns the next character advancing the cursor.
+   *
+   * @return string
+   *   The next character.
+   */
+  protected function readNextChar() {
+    $this->cursor++;
+    return isset($this->expression[$this->cursor]) ? $this->expression[$this->cursor] : '';
+  }
+
+}
diff --git a/core/lib/Drupal/Component/XpathHelper/Namespacer.php b/core/lib/Drupal/Component/XpathHelper/Namespacer.php
new file mode 100644
index 0000000..16be994
--- /dev/null
+++ b/core/lib/Drupal/Component/XpathHelper/Namespacer.php
@@ -0,0 +1,356 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Component\XpathHelper\Namespacer.
+ */
+
+namespace Drupal\Component\XpathHelper;
+
+use Drupal\Component\XpathHelper\Lexer;
+
+/**
+ * XPath expressions namespacer.
+ *
+ * When a DOMDocument has a default namespace it's not possible to parse it
+ * using XPath unless the namespace is registered as something else. This class
+ * provides two methods for working around this limitation.
+ */
+class Namespacer {
+
+  /**
+   * The prefix to assign.
+   *
+   * @var string
+   */
+  protected $prefix;
+
+  /**
+   * The list of tokens from the XPath expression.
+   *
+   * @var []string
+   */
+  protected $tokens;
+
+  /**
+   * The current position in the token list.
+   *
+   * @var int
+   */
+  protected $cursor = 0;
+
+  /**
+   * A cache of rewritten expressions.
+   *
+   * @var array
+   */
+  protected static $cache = array();
+
+  /**
+   * Strings that have operational meaning and shouldn't be namespaced.
+   *
+   * @var array
+   */
+  protected static $operators = array(
+    'or' => TRUE,
+    'and' => TRUE,
+    'div' => TRUE,
+    'mod' => TRUE,
+  );
+
+  /**
+   * Tokens that come before elements.
+   *
+   * @var array
+   */
+  protected static $precedesElement = array(
+    '/' => TRUE,
+    '//' => TRUE,
+    '::' => TRUE,
+    '(' => TRUE,
+    ',' => TRUE,
+    '[' => TRUE,
+  );
+
+  /**
+   * Prefixes an XPath expression.
+   *
+   * Converts an expression from //div/a to //x:div/x:a.
+   *
+   * @param string $xpath
+   *   The XPath expression to prefix.
+   * @param string $prefix
+   *   (optional) The prefix to use. Defaults to "x".
+   *
+   * @return string
+   *   The prefixed XPath expression.
+   */
+  public static function prefix($xpath, $prefix = 'x') {
+    if (!isset(static::$cache[$prefix][$xpath])) {
+      $parser = new static($xpath, $prefix, new Lexer());
+      static::$cache[$prefix][$xpath] = $parser->parse();
+    }
+
+    return static::$cache[$prefix][$xpath];
+  }
+
+  /**
+   * Localizes an XPath expression.
+   *
+   * Converts an expression from //div/a to
+   * //*[local-name() = "div"]/*[local-name() = "a"].
+   *
+   * @param string $xpath
+   *   The XPath expression to prefix.
+   *
+   * @return string
+   *   The localized XPath expression.
+   */
+  public static function localize($xpath) {
+    if (!isset(static::$cache[NULL][$xpath])) {
+      $parser = new static($xpath, NULL, new Lexer());
+      static::$cache[NULL][$xpath] = $parser->parse();
+    }
+
+    return static::$cache[NULL][$xpath];
+  }
+
+  /**
+   * Constructs a Namespacer object.
+   *
+   * @param string $expression
+   *   The XPath expression.
+   * @param string $prefix
+   *   The prefix to use.
+   * @param \Drupal\Component\XpathHelper\Lexer $lexer
+   *   The lexer that will produce tokens.
+   */
+  public function __construct($expression, $prefix, Lexer $lexer) {
+    $this->prefix = $prefix;
+    $this->tokens = $lexer->lex($expression);
+  }
+
+  /**
+   * Parses an XPath expression.
+   *
+   * @return string
+   *   The rewritten XPath expression.
+   */
+  public function parse() {
+    $output = '';
+
+    $token_count = count($this->tokens);
+
+    for ($this->cursor; $this->cursor < $token_count; $this->cursor++) {
+      $token = $this->tokens[$this->cursor];
+
+      // A token that should be copied directly to the output.
+      if ($this->shouldCopy($token)) {
+        $output .= $token;
+      }
+      // A namespaced element.
+      elseif ($element = $this->getNamespacedElement($token)) {
+        $output .= $element;
+      }
+      // Namespace the element.
+      else {
+        $output .= $this->rewrite($token);
+      }
+    }
+
+    return $output;
+  }
+
+  /**
+   * Rewrites the token.
+   *
+   * Either in the form prefix:element or *[local-name() = "element"]
+   *
+   * @param string $token
+   *   The element to rewrite.
+   *
+   * @return string
+   *   The rewritten string.
+   */
+  protected function rewrite($element) {
+    if ($this->prefix) {
+      return $this->prefix . ':' . $element;
+    }
+    return '*[local-name() = "' . $element . '"]';
+  }
+
+  /**
+   * Determines if a token should be copied as-is to the output.
+   *
+   * @param string $token
+   *   The token.
+   *
+   * @return bool
+   *   Returns true if the token should be copied, and false if not.
+   */
+  protected function shouldCopy($token) {
+    if (Lexer::isWordBoundary($token)) {
+      return TRUE;
+    }
+    // Attribute or quoted string.
+    elseif ($token[0] === '@' || $token[0] === '"' || $token[0] === "'") {
+      return TRUE;
+    }
+    elseif (is_numeric($token) || is_numeric($token[0])) {
+      return TRUE;
+    }
+    elseif ($this->isFunctionCall()) {
+      return TRUE;
+    }
+    elseif ($this->isOperator($token)) {
+      return TRUE;
+    }
+    elseif ($this->isAxis()) {
+      return TRUE;
+    }
+    elseif ($this->wasAttributeAxis()) {
+      return TRUE;
+    }
+    // Handles the edge case where subtraction is written like 2 - 1.
+    elseif ($token === '-') {
+      return TRUE;
+    }
+
+    return FALSE;
+  }
+
+  /**
+   * Returns the namespaced element.
+   *
+   * @param string $token
+   *   The token.
+   *
+   * @return string|bool
+   *   The namespaced element, or false if it doesn't exist.
+   */
+  protected function getNamespacedElement($token) {
+    if ($this->peek(1) !== ':') {
+      return FALSE;
+    }
+
+    // Build the namespaced element, prefix:element.
+    $token .= ':' . $this->peek(2);
+    $this->cursor += 2;
+    return $token;
+  }
+
+  /**
+   * Determines if the current token is a function call.
+   *
+   * @param string $token
+   *   The token.
+   *
+   * @return bool
+   *   Returns true if the token is a function call and false if not.
+   */
+  protected function isFunctionCall() {
+    // Spaces before the opening parens of a function call are valid.
+    // Ex: //div[contains   (@id, "thing")]
+    return $this->nextNonSpace() === '(';
+  }
+
+  /**
+   * Checks if a token is an operator, one of div, or, and, mod.
+   *
+   * @param string $token
+   *   The token to check.
+   *
+   * @return bool
+   *   Returns true if the token is an operator, and false if not.
+   */
+  protected function isOperator($token) {
+    if (!isset(static::$operators[$token])) {
+      return FALSE;
+    }
+
+    $prev = $this->prevNonSpace();
+    return $prev && !isset(static::$precedesElement[$prev]);
+  }
+
+  /**
+   * Determines whether this token is an axis.
+   *
+   * descendant-or-self, attribute, etc.
+   *
+   * @return bool
+   *   True if the token is an axis, false if not.
+   */
+  protected function isAxis() {
+    return $this->nextNonSpace() === '::';
+  }
+
+  /**
+   * Determines whether the preceding token was an attribute axis.
+   *
+   * attribute::
+   *
+   * @return bool
+   *   True if the preceding token was an attribute axis, false if not.
+   */
+  protected function wasAttributeAxis() {
+    return $this->prevNonSpace() === '::' && $this->prevNonSpace(2) === 'attribute';
+  }
+
+  /**
+   * Returns the next non-space token.
+   *
+   * @param int $delta
+   *   (optional) The delta of the next non-space character. Defaults to 1.
+   *
+   * @return string
+   *   The nth next non-space character.
+   */
+  protected function nextNonSpace($delta = 1) {
+    $n = 1;
+
+    for ($i = 0; $i < $delta; $i++) {
+      do {
+        $next = $this->peek($n);
+        $n++;
+      } while ($next === ' ');
+    }
+
+    return $next;
+  }
+
+  /**
+   * Returns the previous non-space token.
+   *
+   * @param int $delta
+   *   (optional) The delta of the previous non-space character. Defaults to 1.
+   *
+   * @return string
+   *   The nth previous non-space character.
+   */
+  protected function prevNonSpace($delta = 1) {
+    $n = -1;
+
+    for ($i = 0; $i < $delta; $i++) {
+      do {
+        $prev = $this->peek($n);
+        $n--;
+      } while ($prev === ' ');
+    }
+
+    return $prev;
+  }
+
+  /**
+   * Returns a token from an offset of the current position.
+   *
+   * @param int $offset
+   *   The offset from the current position.
+   *
+   * @return string
+   *   Returns the token at the given offset.
+   */
+  protected function peek($offset) {
+    return isset($this->tokens[$this->cursor + $offset]) ? $this->tokens[$this->cursor + $offset] : '';
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Entity/Entity.php b/core/lib/Drupal/Core/Entity/Entity.php
index c76dc40..4ef2926 100644
--- a/core/lib/Drupal/Core/Entity/Entity.php
+++ b/core/lib/Drupal/Core/Entity/Entity.php
@@ -147,7 +147,7 @@ public function label() {
       $label = call_user_func($label_callback, $this);
     }
     elseif (($label_key = $entity_type->getKey('label')) && isset($this->{$label_key})) {
-      $label = $this->{$label_key};
+      $label = (string) $this->{$label_key};
     }
     return $label;
   }
diff --git a/core/modules/aggregator/src/Tests/AggregatorRenderingTest.php b/core/modules/aggregator/src/Tests/AggregatorRenderingTest.php
index efb3d2f..2e0e422 100644
--- a/core/modules/aggregator/src/Tests/AggregatorRenderingTest.php
+++ b/core/modules/aggregator/src/Tests/AggregatorRenderingTest.php
@@ -123,7 +123,7 @@ public function testFeedPage() {
     $outline = $this->xpath('//outline[1]');
     $this->assertEqual($outline[0]['type'], 'rss', 'The correct type attribute is used for rss OPML.');
     $this->assertEqual($outline[0]['text'], $feed->label(), 'The correct text attribute is used for rss OPML.');
-    $this->assertEqual($outline[0]['xmlurl'], $feed->getUrl(), 'The correct xmlUrl attribute is used for rss OPML.');
+    $this->assertEqual($outline[0]['xmlUrl'], $feed->getUrl(), 'The correct xmlUrl attribute is used for rss OPML.');
 
     // Check for the presence of a pager.
     $this->drupalGet('aggregator/sources/' . $feed->id());
diff --git a/core/modules/comment/src/Tests/Views/RowRssTest.php b/core/modules/comment/src/Tests/Views/RowRssTest.php
index 89b9c1b..4536652 100644
--- a/core/modules/comment/src/Tests/Views/RowRssTest.php
+++ b/core/modules/comment/src/Tests/Views/RowRssTest.php
@@ -31,7 +31,7 @@ public function testRssRow() {
     $result = $this->xpath('//item');
     $this->assertEqual(count($result), 1, 'Just one comment was found in the rss output.');
 
-    $this->assertEqual($result[0]->pubdate, gmdate('r', $this->comment->getCreatedTime()), 'The right pubDate appears in the rss output.');
+    $this->assertEqual($result[0]->pubDate, gmdate('r', $this->comment->getCreatedTime()), 'The right pubDate appears in the rss output.');
   }
 
 }
diff --git a/core/modules/config/src/Tests/ConfigEntityListTest.php b/core/modules/config/src/Tests/ConfigEntityListTest.php
index c578ff2..8f90ff9 100644
--- a/core/modules/config/src/Tests/ConfigEntityListTest.php
+++ b/core/modules/config/src/Tests/ConfigEntityListTest.php
@@ -174,7 +174,7 @@ function testListUI() {
     // operations list.
     $this->assertIdentical((string) $elements[0], 'Default');
     $this->assertIdentical((string) $elements[1], 'dotted.default');
-    $this->assertTrue($elements[2]->children()->xpath('//ul'), 'Operations list found.');
+    $this->assertTrue($elements[2]->children()->xpath($this->localizeXpath('//ul')), 'Operations list found.');
 
     // Add a new entity using the operations link.
     $this->assertLink('Add test configuration');
diff --git a/core/modules/editor/editor.admin.inc b/core/modules/editor/editor.admin.inc
index 83bc2cf..67ebedf 100644
--- a/core/modules/editor/editor.admin.inc
+++ b/core/modules/editor/editor.admin.inc
@@ -92,8 +92,8 @@ function editor_image_upload_settings_form(Editor $editor) {
   $form['max_dimensions'] = array(
     '#type' => 'item',
     '#title' => t('Maximum dimensions'),
-    '#field_prefix' => '<div class="container-inline clearfix">',
-    '#field_suffix' => '</div>',
+    // '#field_prefix' => '<div class="container-inline clearfix">',
+    // '#field_suffix' => '</div>',
     '#description' => t('Images larger than these dimensions will be scaled down.'),
     '#states' => $show_if_image_uploads_enabled,
   );
diff --git a/core/modules/editor/src/Tests/QuickEditIntegrationLoadingTest.php b/core/modules/editor/src/Tests/QuickEditIntegrationLoadingTest.php
index c4b81ea..6e7316d 100644
--- a/core/modules/editor/src/Tests/QuickEditIntegrationLoadingTest.php
+++ b/core/modules/editor/src/Tests/QuickEditIntegrationLoadingTest.php
@@ -85,7 +85,10 @@ public function testUsersWithoutPermission() {
       $this->drupalGet('node/1');
 
       // Ensure the text is transformed.
-      $this->assertRaw('<p>Do you also love Drupal?</p><figure class="caption caption-img"><img src="druplicon.png" /><figcaption>Druplicon</figcaption></figure>');
+      $this->assertRaw('<p>Do you also love Drupal?</p><figure class="caption caption-img">
+<img src="druplicon.png">
+<figcaption>Druplicon</figcaption>
+</figure>');
 
       // Retrieving the untransformed text should result in an empty 403 response.
       $response = $this->drupalPost('editor/' . 'node/1/body/en/full', 'application/vnd.drupal-ajax', array());
@@ -103,7 +106,10 @@ public function testUserWithPermission() {
     $this->drupalGet('node/1');
 
     // Ensure the text is transformed.
-    $this->assertRaw('<p>Do you also love Drupal?</p><figure class="caption caption-img"><img src="druplicon.png" /><figcaption>Druplicon</figcaption></figure>');
+    $this->assertRaw('<p>Do you also love Drupal?</p><figure class="caption caption-img">
+<img src="druplicon.png">
+<figcaption>Druplicon</figcaption>
+</figure>');
 
     $response = $this->drupalPost('editor/' . 'node/1/body/en/full', 'application/vnd.drupal-ajax', array());
     $this->assertResponse(200);
diff --git a/core/modules/filter/src/Tests/FilterUnitTest.php b/core/modules/filter/src/Tests/FilterUnitTest.php
index 8d06de7..96b7b79 100644
--- a/core/modules/filter/src/Tests/FilterUnitTest.php
+++ b/core/modules/filter/src/Tests/FilterUnitTest.php
@@ -57,40 +57,40 @@ function testAlignFilter() {
 
     // Data-align attribute: all 3 allowed values.
     $input = '<img src="llama.jpg" data-align="left" />';
-    $expected = '<img src="llama.jpg" class="align-left" />';
+    $expected = '<img src="llama.jpg" class="align-left">';
     $this->assertIdentical($expected, $test($input)->getProcessedText());
-    $input = '<img src="llama.jpg" data-align="center" />';
-    $expected = '<img src="llama.jpg" class="align-center" />';
+    $input = '<img src="llama.jpg" data-align="center">';
+    $expected = '<img src="llama.jpg" class="align-center">';
     $this->assertIdentical($expected, $test($input)->getProcessedText());
     $input = '<img src="llama.jpg" data-align="right" />';
-    $expected = '<img src="llama.jpg" class="align-right" />';
+    $expected = '<img src="llama.jpg" class="align-right">';
     $this->assertIdentical($expected, $test($input)->getProcessedText());
 
     // Data-align attribute: a disallowed value.
     $input = '<img src="llama.jpg" data-align="left foobar" />';
-    $expected = '<img src="llama.jpg" />';
+    $expected = '<img src="llama.jpg">';
     $this->assertIdentical($expected, $test($input)->getProcessedText());
 
     // Empty data-align attribute.
     $input = '<img src="llama.jpg" data-align="" />';
-    $expected = '<img src="llama.jpg" />';
+    $expected = '<img src="llama.jpg">';
     $this->assertIdentical($expected, $test($input)->getProcessedText());
 
     // Ensure the filter also works with uncommon yet valid attribute quoting.
     $input = '<img src=llama.jpg data-align=right />';
-    $expected = '<img src="llama.jpg" class="align-right" />';
+    $expected = '<img src="llama.jpg" class="align-right">';
     $output = $test($input);
     $this->assertIdentical($expected, $output->getProcessedText());
 
     // Security test: attempt to inject an additional class.
     $input = '<img src="llama.jpg" data-align="center another-class-here" />';
-    $expected = '<img src="llama.jpg" />';
+    $expected = '<img src="llama.jpg">';
     $output = $test($input);
     $this->assertIdentical($expected, $output->getProcessedText());
 
     // Security test: attempt an XSS.
     $input = '<img src="llama.jpg" data-align="center \'onclick=\'alert(foo);" />';
-    $expected = '<img src="llama.jpg" />';
+    $expected = '<img src="llama.jpg">';
     $output = $test($input);
     $this->assertIdentical($expected, $output->getProcessedText());
   }
@@ -118,26 +118,35 @@ function testCaptionFilter() {
 
     // Data-caption attribute.
     $input = '<img src="llama.jpg" data-caption="Loquacious llama!" />';
-    $expected = '<figure class="caption caption-img"><img src="llama.jpg" /><figcaption>Loquacious llama!</figcaption></figure>';
+    $expected = '<figure class="caption caption-img">
+<img src="llama.jpg">
+<figcaption>Loquacious llama!</figcaption>
+</figure>';
     $output = $test($input);
     $this->assertIdentical($expected, $output->getProcessedText());
     $this->assertIdentical($attached_library, $output->getAssets());
 
     // Empty data-caption attribute.
     $input = '<img src="llama.jpg" data-caption="" />';
-    $expected = '<img src="llama.jpg" />';
+    $expected = '<img src="llama.jpg">';
     $this->assertIdentical($expected, $test($input)->getProcessedText());
 
     // HTML entities in the caption.
     $input = '<img src="llama.jpg" data-caption="&ldquo;Loquacious llama!&rdquo;" />';
-    $expected = '<figure class="caption caption-img"><img src="llama.jpg" /><figcaption>“Loquacious llama!”</figcaption></figure>';
+    $expected = '<figure class="caption caption-img">
+<img src="llama.jpg">
+<figcaption>“Loquacious llama!”</figcaption>
+</figure>';
     $output = $test($input);
     $this->assertIdentical($expected, $output->getProcessedText());
     $this->assertIdentical($attached_library, $output->getAssets());
 
     // HTML encoded as HTML entities in data-caption attribute.
     $input = '<img src="llama.jpg" data-caption="&lt;em&gt;Loquacious llama!&lt;/em&gt;" />';
-    $expected = '<figure class="caption caption-img"><img src="llama.jpg" /><figcaption><em>Loquacious llama!</em></figcaption></figure>';
+    $expected = '<figure class="caption caption-img">
+<img src="llama.jpg">
+<figcaption><em>Loquacious llama!</em></figcaption>
+</figure>';
     $output = $test($input);
     $this->assertIdentical($expected, $output->getProcessedText());
     $this->assertIdentical($attached_library, $output->getAssets());
@@ -146,33 +155,48 @@ function testCaptionFilter() {
     // not allowed by the HTML spec, but may happen when people manually write
     // HTML, so we explicitly support it.
     $input = '<img src="llama.jpg" data-caption="<em>Loquacious llama!</em>" />';
-    $expected = '<figure class="caption caption-img"><img src="llama.jpg" /><figcaption><em>Loquacious llama!</em></figcaption></figure>';
+    $expected = '<figure class="caption caption-img">
+<img src="llama.jpg">
+<figcaption><em>Loquacious llama!</em></figcaption>
+</figure>';
     $output = $test($input);
     $this->assertIdentical($expected, $output->getProcessedText());
     $this->assertIdentical($attached_library, $output->getAssets());
 
     // Security test: attempt an XSS.
     $input = '<img src="llama.jpg" data-caption="<script>alert(\'Loquacious llama!\')</script>" />';
-    $expected = '<figure class="caption caption-img"><img src="llama.jpg" /><figcaption>alert(\'Loquacious llama!\')</figcaption></figure>';
+    $expected = '<figure class="caption caption-img">
+<img src="llama.jpg">
+<figcaption>alert(\'Loquacious llama!\')</figcaption>
+</figure>';
     $output = $test($input);
     $this->assertIdentical($expected, $output->getProcessedText());
     $this->assertIdentical($attached_library, $output->getAssets());
 
     // Ensure the filter also works with uncommon yet valid attribute quoting.
     $input = '<img src=llama.jpg data-caption=\'Loquacious llama!\' />';
-    $expected = '<figure class="caption caption-img"><img src="llama.jpg" /><figcaption>Loquacious llama!</figcaption></figure>';
+    $expected = '<figure class="caption caption-img">
+<img src="llama.jpg">
+<figcaption>Loquacious llama!</figcaption>
+</figure>';
     $output = $test($input);
     $this->assertIdentical($expected, $output->getProcessedText());
     $this->assertIdentical($attached_library, $output->getAssets());
 
     // Finally, ensure that this also works on any other tag.
     $input = '<video src="llama.jpg" data-caption="Loquacious llama!" />';
-    $expected = '<figure class="caption caption-video"><video src="llama.jpg"></video><figcaption>Loquacious llama!</figcaption></figure>';
+    $expected = '<figure class="caption caption-video">
+<video src="llama.jpg"></video>
+<figcaption>Loquacious llama!</figcaption>
+</figure>';
     $output = $test($input);
     $this->assertIdentical($expected, $output->getProcessedText());
     $this->assertIdentical($attached_library, $output->getAssets());
     $input = '<foobar data-caption="Loquacious llama!">baz</foobar>';
-    $expected = '<figure class="caption caption-foobar"><foobar>baz</foobar><figcaption>Loquacious llama!</figcaption></figure>';
+    $expected = '<figure class="caption caption-foobar">
+<foobar>baz</foobar>
+<figcaption>Loquacious llama!</figcaption>
+</figure>';
     $output = $test($input);
     $this->assertIdentical($expected, $output->getProcessedText());
     $this->assertIdentical($attached_library, $output->getAssets());
@@ -198,17 +222,26 @@ function testAlignAndCaptionFilters() {
     // Both data-caption and data-align attributes: all 3 allowed values for the
     // data-align attribute.
     $input = '<img src="llama.jpg" data-caption="Loquacious llama!" data-align="left" />';
-    $expected = '<figure class="caption caption-img align-left"><img src="llama.jpg" /><figcaption>Loquacious llama!</figcaption></figure>';
+    $expected = '<figure class="caption caption-img align-left">
+<img src="llama.jpg">
+<figcaption>Loquacious llama!</figcaption>
+</figure>';
     $output = $test($input);
     $this->assertIdentical($expected, $output->getProcessedText());
     $this->assertIdentical($attached_library, $output->getAssets());
     $input = '<img src="llama.jpg" data-caption="Loquacious llama!" data-align="center" />';
-    $expected = '<figure class="caption caption-img align-center"><img src="llama.jpg" /><figcaption>Loquacious llama!</figcaption></figure>';
+    $expected = '<figure class="caption caption-img align-center">
+<img src="llama.jpg">
+<figcaption>Loquacious llama!</figcaption>
+</figure>';
     $output = $test($input);
     $this->assertIdentical($expected, $output->getProcessedText());
     $this->assertIdentical($attached_library, $output->getAssets());
     $input = '<img src="llama.jpg" data-caption="Loquacious llama!" data-align="right" />';
-    $expected = '<figure class="caption caption-img align-right"><img src="llama.jpg" /><figcaption>Loquacious llama!</figcaption></figure>';
+    $expected = '<figure class="caption caption-img align-right">
+<img src="llama.jpg">
+<figcaption>Loquacious llama!</figcaption>
+</figure>';
     $output = $test($input);
     $this->assertIdentical($expected, $output->getProcessedText());
     $this->assertIdentical($attached_library, $output->getAssets());
@@ -216,7 +249,10 @@ function testAlignAndCaptionFilters() {
     // Both data-caption and data-align attributes, but a disallowed data-align
     // attribute value.
     $input = '<img src="llama.jpg" data-caption="Loquacious llama!" data-align="left foobar" />';
-    $expected = '<figure class="caption caption-img"><img src="llama.jpg" /><figcaption>Loquacious llama!</figcaption></figure>';
+    $expected = '<figure class="caption caption-img">
+<img src="llama.jpg">
+<figcaption>Loquacious llama!</figcaption>
+</figure>';
     $output = $test($input);
     $this->assertIdentical($expected, $output->getProcessedText());
     $this->assertIdentical($attached_library, $output->getAssets());
@@ -825,7 +861,7 @@ function testHtmlCorrectorFilter() {
 
     // XHTML slash for empty elements.
     $f = Html::normalize('<hr><br>');
-    $this->assertEqual($f, '<hr /><br />', 'HTML corrector -- XHTML closing slash.');
+    $this->assertEqual($f, '<hr><br>', 'HTML corrector -- XHTML closing slash is not added.');
 
     $f = Html::normalize('<P>test</P>');
     $this->assertEqual($f, '<p>test</p>', 'HTML corrector -- Convert uppercased tags to proper lowercased ones.');
@@ -834,37 +870,28 @@ function testHtmlCorrectorFilter() {
     $this->assertEqual($f, '<p>test</p>', 'HTML corrector -- Convert uppercased tags to proper lowercased ones.');
 
     $f = Html::normalize('test<hr />');
-    $this->assertEqual($f, 'test<hr />', 'HTML corrector -- Let proper XHTML pass through.');
+    $this->assertEqual($f, 'test<hr>', 'HTML corrector -- XHTML closing slash is removed.');
 
     $f = Html::normalize('test<hr/>');
-    $this->assertEqual($f, 'test<hr />', 'HTML corrector -- Let proper XHTML pass through, but ensure there is a single space before the closing slash.');
+    $this->assertEqual($f, 'test<hr>', 'HTML corrector -- XHTML closing slash is removed, even if there is no space before it.');
 
     $f = Html::normalize('test<hr    />');
-    $this->assertEqual($f, 'test<hr />', 'HTML corrector -- Let proper XHTML pass through, but ensure there are not too many spaces before the closing slash.');
+    $this->assertEqual($f, 'test<hr>', 'HTML corrector -- XHTML closing slash is removed, even if there are many spaces before it.');
 
     $f = Html::normalize('<span class="test" />');
     $this->assertEqual($f, '<span class="test"></span>', 'HTML corrector -- Convert XHTML that is properly formed but that would not be compatible with typical HTML user agents.');
 
     $f = Html::normalize('test1<br class="test">test2');
-    $this->assertEqual($f, 'test1<br class="test" />test2', 'HTML corrector -- Automatically close single tags.');
-
-    $f = Html::normalize('line1<hr>line2');
-    $this->assertEqual($f, 'line1<hr />line2', 'HTML corrector -- Automatically close single tags.');
-
-    $f = Html::normalize('line1<HR>line2');
-    $this->assertEqual($f, 'line1<hr />line2', 'HTML corrector -- Automatically close single tags.');
-
-    $f = Html::normalize('<img src="http://example.com/test.jpg">test</img>');
-    $this->assertEqual($f, '<img src="http://example.com/test.jpg" />test', 'HTML corrector -- Automatically close single tags.');
+    $this->assertEqual($f, 'test1<br class="test">test2', 'HTML corrector -- Single tags do not get an XHTML closing slash..');
 
     $f = Html::normalize('<br></br>');
-    $this->assertEqual($f, '<br />', "HTML corrector -- Transform empty tags to a single closed tag if the tag's content model is EMPTY.");
+    $this->assertEqual($f, '<br>', "HTML corrector -- Transform empty tags to a single tag if the tag's content model is EMPTY.");
 
     $f = Html::normalize('<div></div>');
     $this->assertEqual($f, '<div></div>', "HTML corrector -- Do not transform empty tags to a single closed tag if the tag's content model is not EMPTY.");
 
     $f = Html::normalize('<p>line1<br/><hr/>line2</p>');
-    $this->assertEqual($f, '<p>line1<br /></p><hr />line2', 'HTML corrector -- Move non-inline elements outside of inline containers.');
+    $this->assertEqual($f, '<p>line1<br></p><hr>line2', 'HTML corrector -- Move non-inline elements outside of inline containers.');
 
     $f = Html::normalize('<p>line1<div>line2</div></p>');
     $this->assertEqual($f, '<p>line1</p><div>line2</div>', 'HTML corrector -- Move non-inline elements outside of inline containers.');
@@ -873,7 +900,7 @@ function testHtmlCorrectorFilter() {
     $this->assertEqual($f, '<p>test</p><p>test</p>\n', 'HTML corrector -- Auto-close improperly nested tags.');
 
     $f = Html::normalize('<p>Line1<br><STRONG>bold stuff</b>');
-    $this->assertEqual($f, '<p>Line1<br /><strong>bold stuff</strong></p>', 'HTML corrector -- Properly close unclosed tags, and remove useless closing tags.');
+    $this->assertEqual($f, '<p>Line1<br><strong>bold stuff</strong></p>', 'HTML corrector -- Useless closing tags are removed.');
 
     $f = Html::normalize('test <!-- this is a comment -->');
     $this->assertEqual($f, 'test <!-- this is a comment -->', 'HTML corrector -- Do not touch HTML comments.');
@@ -899,100 +926,6 @@ function testHtmlCorrectorFilter() {
 
     $f = Html::normalize('<p>دروبال');
     $this->assertEqual($f, '<p>دروبال</p>', 'HTML corrector -- Encoding is correctly kept.');
-
-    $f = Html::normalize('<script>alert("test")</script>');
-    $this->assertEqual($f, '<script>
-<!--//--><![CDATA[// ><!--
-alert("test")
-//--><!]]>
-</script>', 'HTML corrector -- CDATA added to script element');
-
-    $f = Html::normalize('<p><script>alert("test")</script></p>');
-    $this->assertEqual($f, '<p><script>
-<!--//--><![CDATA[// ><!--
-alert("test")
-//--><!]]>
-</script></p>', 'HTML corrector -- CDATA added to a nested script element');
-
-    $f = Html::normalize('<p><style> /* Styling */ body {color:red}</style></p>');
-    $this->assertEqual($f, '<p><style>
-<!--/*--><![CDATA[/* ><!--*/
- /* Styling */ body {color:red}
-/*--><!]]>*/
-</style></p>', 'HTML corrector -- CDATA added to a style element.');
-
-    $filtered_data = Html::normalize('<p><style>
-/*<![CDATA[*/
-/* Styling */
-body {color:red}
-/*]]>*/
-</style></p>');
-    $this->assertEqual($filtered_data, '<p><style>
-<!--/*--><![CDATA[/* ><!--*/
-
-/*<![CDATA[*/
-/* Styling */
-body {color:red}
-/*]]]]><![CDATA[>*/
-
-/*--><!]]>*/
-</style></p>',
-      format_string('HTML corrector -- Existing cdata section @pattern_name properly escaped', array('@pattern_name' => '/*<![CDATA[*/'))
-    );
-
-    $filtered_data = Html::normalize('<p><style>
-  <!--/*--><![CDATA[/* ><!--*/
-  /* Styling */
-  body {color:red}
-  /*--><!]]>*/
-</style></p>');
-    $this->assertEqual($filtered_data, '<p><style>
-<!--/*--><![CDATA[/* ><!--*/
-
-  <!--/*--><![CDATA[/* ><!--*/
-  /* Styling */
-  body {color:red}
-  /*--><!]]]]><![CDATA[>*/
-
-/*--><!]]>*/
-</style></p>',
-      format_string('HTML corrector -- Existing cdata section @pattern_name properly escaped', array('@pattern_name' => '<!--/*--><![CDATA[/* ><!--*/'))
-    );
-
-    $filtered_data = Html::normalize('<p><script>
-<!--//--><![CDATA[// ><!--
-  alert("test");
-//--><!]]>
-</script></p>');
-    $this->assertEqual($filtered_data, '<p><script>
-<!--//--><![CDATA[// ><!--
-
-<!--//--><![CDATA[// ><!--
-  alert("test");
-//--><!]]]]><![CDATA[>
-
-//--><!]]>
-</script></p>',
-      format_string('HTML corrector -- Existing cdata section @pattern_name properly escaped', array('@pattern_name' => '<!--//--><![CDATA[// ><!--'))
-    );
-
-    $filtered_data = Html::normalize('<p><script>
-// <![CDATA[
-  alert("test");
-// ]]>
-</script></p>');
-    $this->assertEqual($filtered_data, '<p><script>
-<!--//--><![CDATA[// ><!--
-
-// <![CDATA[
-  alert("test");
-// ]]]]><![CDATA[>
-
-//--><!]]>
-</script></p>',
-      format_string('HTML corrector -- Existing cdata section @pattern_name properly escaped', array('@pattern_name' => '// <![CDATA['))
-    );
-
   }
 
   /**
diff --git a/core/modules/image/src/Plugin/Field/FieldType/ImageItem.php b/core/modules/image/src/Plugin/Field/FieldType/ImageItem.php
index 4e49b81..0e5ee51 100644
--- a/core/modules/image/src/Plugin/Field/FieldType/ImageItem.php
+++ b/core/modules/image/src/Plugin/Field/FieldType/ImageItem.php
@@ -206,8 +206,8 @@ public function fieldSettingsForm(array $form, FormStateInterface $form_state) {
       '#title' => t('Maximum image resolution'),
       '#element_validate' => array(array(get_class($this), 'validateResolution')),
       '#weight' => 4.1,
-      '#field_prefix' => '<div class="container-inline">',
-      '#field_suffix' => '</div>',
+      // '#field_prefix' => '<div class="container-inline">',
+      // '#field_suffix' => '</div>',
       '#description' => t('The maximum allowed image size expressed as WIDTH×HEIGHT (e.g. 640×480). Leave blank for no restriction. If a larger image is uploaded, it will be resized to reflect the given width and height. Resizing images on upload will cause the loss of <a href="@url">EXIF data</a> in the image.', array('@url' => 'http://en.wikipedia.org/wiki/Exchangeable_image_file_format')),
     );
     $element['max_resolution']['x'] = array(
@@ -233,8 +233,8 @@ public function fieldSettingsForm(array $form, FormStateInterface $form_state) {
       '#title' => t('Minimum image resolution'),
       '#element_validate' => array(array(get_class($this), 'validateResolution')),
       '#weight' => 4.2,
-      '#field_prefix' => '<div class="container-inline">',
-      '#field_suffix' => '</div>',
+      // '#field_prefix' => '<div class="container-inline">',
+      // '#field_suffix' => '</div>',
       '#description' => t('The minimum allowed image size expressed as WIDTH×HEIGHT (e.g. 640×480). Leave blank for no restriction. If a smaller image is uploaded, it will be rejected.'),
     );
     $element['min_resolution']['x'] = array(
diff --git a/core/modules/image/src/Tests/ImageFieldDisplayTest.php b/core/modules/image/src/Tests/ImageFieldDisplayTest.php
index f006abd..3c82d03 100644
--- a/core/modules/image/src/Tests/ImageFieldDisplayTest.php
+++ b/core/modules/image/src/Tests/ImageFieldDisplayTest.php
@@ -290,8 +290,8 @@ function testImageFieldSettings() {
     $edit = array();
     $edit['files[' . $field_name . '_2][]'] = drupal_realpath($test_image->uri);
     $this->drupalPostAjaxForm(NULL, $edit, $field_name . '_2_upload_button');
-    $this->assertNoRaw('<input multiple type="file" id="edit-' . strtr($field_name, '_', '-') . '-2-upload" name="files[' . $field_name . '_2][]" size="22" class="form-file">');
-    $this->assertRaw('<input multiple type="file" id="edit-' . strtr($field_name, '_', '-') . '-3-upload" name="files[' . $field_name . '_3][]" size="22" class="form-file">');
+    $this->assertNoRaw('<input multiple="multiple" type="file" id="edit-' . strtr($field_name, '_', '-') . '-2-upload" name="files[' . $field_name . '_2][]" size="22" class="form-file">');
+    $this->assertRaw('<input multiple="multiple" type="file" id="edit-' . strtr($field_name, '_', '-') . '-3-upload" name="files[' . $field_name . '_3][]" size="22" class="form-file">');
   }
 
   /**
diff --git a/core/modules/rdf/src/Tests/Field/FieldRdfaTestBase.php b/core/modules/rdf/src/Tests/Field/FieldRdfaTestBase.php
index adddda1..7e702b0 100644
--- a/core/modules/rdf/src/Tests/Field/FieldRdfaTestBase.php
+++ b/core/modules/rdf/src/Tests/Field/FieldRdfaTestBase.php
@@ -7,6 +7,7 @@
 namespace Drupal\rdf\Tests\Field;
 
 use Drupal\field\Tests\FieldUnitTestBase;
+use Masterminds\HTML5;
 
 abstract class FieldRdfaTestBase extends FieldUnitTestBase {
 
@@ -151,8 +152,8 @@ protected function getAbsoluteUri($entity) {
    *   An array containing simplexml objects.
    */
   protected function parseContent($content) {
-    $htmlDom = new \DOMDocument();
-    @$htmlDom->loadHTML('<?xml encoding="UTF-8">' . $content);
+    $html5 = new HTML5();
+    $htmlDom = $html5->loadHTML($content);
     $elements = simplexml_import_dom($htmlDom);
 
     return $elements;
@@ -178,6 +179,14 @@ protected function parseContent($content) {
   protected function xpathContent($content, $xpath, array $arguments = array()) {
     if ($elements = $this->parseContent($content)) {
       $xpath = $this->buildXPathQuery($xpath, $arguments);
+
+      // Register the default namespace if it exists.
+      $namespaces = $elements->getDocNamespaces();
+      if (!empty($namespaces[''])) {
+        $xpath = $this->prefixXpath($xpath);
+        $elements->registerXPathNamespace('x', $namespaces['']);
+      }
+
       $result = $elements->xpath($xpath);
       // Some combinations of PHP / libxml versions return an empty array
       // instead of the documented FALSE. Forcefully convert any falsish values
diff --git a/core/modules/simpletest/src/AssertContentTrait.php b/core/modules/simpletest/src/AssertContentTrait.php
index e114ebf..942b3e1 100644
--- a/core/modules/simpletest/src/AssertContentTrait.php
+++ b/core/modules/simpletest/src/AssertContentTrait.php
@@ -10,6 +10,8 @@
 use Drupal\Component\Serialization\Json;
 use Drupal\Component\Utility\String;
 use Drupal\Component\Utility\Xss;
+use Drupal\Component\XpathHelper\Namespacer;
+use Masterminds\HTML5;
 use Symfony\Component\CssSelector\CssSelector;
 
 /**
@@ -122,15 +124,22 @@ protected function setDrupalSettings($settings) {
    */
   protected function parse() {
     if (!isset($this->elements)) {
-      // DOM can load HTML soup. But, HTML soup can throw warnings, suppress
-      // them.
-      $html_dom = new \DOMDocument();
-      @$html_dom->loadHTML('<?xml encoding="UTF-8">' . $this->getRawContent());
-      if ($html_dom) {
-        $this->pass(String::format('Valid HTML found on "@path"', array('@path' => $this->getUrl())), 'Browser');
+
+      // Check for XML preamble.
+      if (substr($this->getRawContent(), 0, 5) === '<?xml') {
+        $dom = new \DOMDocument();
+        $dom->loadXML($this->getRawContent());
+      }
+      else {
+        $html5 = new HTML5();
+        $dom = $html5->loadHTML($this->getRawContent());
+      }
+
+      if ($dom) {
+        $this->pass(String::format('Valid markup found on "@path"', array('@path' => $this->getUrl())), 'Browser');
         // It's much easier to work with simplexml than DOM, luckily enough
         // we can just simply import our DOM tree.
-        $this->elements = simplexml_import_dom($html_dom);
+        $this->elements = simplexml_import_dom($dom);
       }
     }
     if ($this->elements === FALSE) {
@@ -219,6 +228,14 @@ protected function buildXPathQuery($xpath, array $args = array()) {
   protected function xpath($xpath, array $arguments = array()) {
     if ($this->parse()) {
       $xpath = $this->buildXPathQuery($xpath, $arguments);
+
+      // Register the default namespace if it exists.
+      $namespaces = $this->elements->getDocNamespaces();
+      if (!empty($namespaces[''])) {
+        $xpath = $this->prefixXpath($xpath);
+        $this->elements->registerXPathNamespace('x', $namespaces['']);
+      }
+
       $result = $this->elements->xpath($xpath);
       // Some combinations of PHP / libxml versions return an empty array
       // instead of the documented FALSE. Forcefully convert any falsish values
@@ -231,6 +248,32 @@ protected function xpath($xpath, array $arguments = array()) {
   }
 
   /**
+   * Prefixes an xpath expression.
+   *
+   * @param string $xpath
+   *   The xpath expression.
+   *
+   * @return string
+   *   The prefixed xpath expression.
+   */
+  protected function prefixXpath($xpath) {
+    return Namespacer::prefix($xpath);
+  }
+
+  /**
+   * Localizes an xpath expression.
+   *
+   * @param string $xpath
+   *   The xpath expression.
+   *
+   * @return string
+   *   The localized xpath expression.
+   */
+  protected function localizeXpath($xpath) {
+    return Namespacer::localize($xpath);
+  }
+
+  /**
    * Searches elements using a CSS selector in the raw content.
    *
    * The search is relative to the root element (HTML tag normally) of the page.
diff --git a/core/modules/simpletest/src/WebTestBase.php b/core/modules/simpletest/src/WebTestBase.php
index ec190a0..a784543 100644
--- a/core/modules/simpletest/src/WebTestBase.php
+++ b/core/modules/simpletest/src/WebTestBase.php
@@ -27,6 +27,7 @@
 use Drupal\Core\StreamWrapper\PublicStream;
 use Drupal\Core\Datetime\DrupalDateTime;
 use Drupal\block\Entity\Block;
+use Masterminds\HTML5;
 use Symfony\Component\HttpFoundation\Request;
 use Drupal\user\Entity\Role;
 
@@ -1850,8 +1851,8 @@ protected function drupalProcessAjaxResponse($content, array $ajax_response, arr
     );
     // DOM can load HTML soup. But, HTML soup can throw warnings, suppress
     // them.
-    $dom = new \DOMDocument();
-    @$dom->loadHTML($content);
+    $html5 = new HTML5();
+    $dom = $html5->loadHTML($content);
     // XPath allows for finding wrapper nodes better than DOM does.
     $xpath = new \DOMXPath($dom);
     foreach ($ajax_response as $command) {
@@ -1876,12 +1877,11 @@ protected function drupalProcessAjaxResponse($content, array $ajax_response, arr
           //   and 'body', since these are used by
           //   \Drupal\Core\Ajax\AjaxResponse::ajaxRender().
           elseif (in_array($command['selector'], array('head', 'body'))) {
-            $wrapperNode = $xpath->query('//' . $command['selector'])->item(0);
+            $wrapperNode = $xpath->query($this->localizeXpath('//' . $command['selector']))->item(0);
           }
           if ($wrapperNode) {
             // ajax.js adds an enclosing DIV to work around a Safari bug.
-            $newDom = new \DOMDocument();
-            @$newDom->loadHTML('<div>' . $command['data'] . '</div>');
+            $newDom = $html5->loadHTML('<div>' . trim($command['data']) . '</div>');
             $newNode = $dom->importNode($newDom->documentElement->firstChild->firstChild, TRUE);
             $method = isset($command['method']) ? $command['method'] : $ajax_settings['method'];
             // The "method" is a jQuery DOM manipulation function. Emulate
@@ -1931,14 +1931,14 @@ protected function drupalProcessAjaxResponse($content, array $ajax_response, arr
         case 'add_css':
           break;
         case 'update_build_id':
-          $buildId = $xpath->query('//input[@name="form_build_id" and @value="' . $command['old'] . '"]')->item(0);
+          $buildId = $xpath->query($this->localizeXpath('//input[@name="form_build_id" and @value="' . $command['old'] . '"]'))->item(0);
           if ($buildId) {
             $buildId->setAttribute('value', $command['new']);
           }
           break;
       }
     }
-    $content = $dom->saveHTML();
+    $content = $html5->saveHTML($dom);
     $this->setRawContent($content);
     $this->setDrupalSettings($drupal_settings);
   }
@@ -2061,11 +2061,11 @@ protected function cronRun() {
    */
   protected function checkForMetaRefresh() {
     if (strpos($this->getRawContent(), '<meta ') && $this->parse()) {
-      $refresh = $this->xpath('//meta[@http-equiv="Refresh"]');
-      if (!empty($refresh)) {
+      preg_match('|<meta\s*http-equiv\s*=\s*"Refresh"\s*content="(.*)"\s*/>|', $this->getRawContent(), $matches);
+      if ($matches) {
         // Parse the content attribute of the meta tag for the format:
         // "[delay]: URL=[page_to_redirect_to]".
-        if (preg_match('/\d+;\s*URL=(?<url>.*)/i', $refresh[0]['content'], $match)) {
+        if (preg_match('/\d+;\s*URL=(?<url>.*)/i', $matches[1], $match)) {
           return $this->drupalGet($this->getAbsoluteUrl(String::decodeEntities($match['url'])));
         }
       }
@@ -2123,7 +2123,7 @@ protected function drupalHead($path, array $options = array(), array $headers =
    */
   protected function handleForm(&$post, &$edit, &$upload, $submit, $form) {
     // Retrieve the form elements.
-    $elements = $form->xpath('.//input[not(@disabled)]|.//textarea[not(@disabled)]|.//select[not(@disabled)]');
+    $elements = $form->xpath($this->localizeXpath('.//input[not(@disabled)]|.//textarea[not(@disabled)]|.//select[not(@disabled)]'));
     $submit_matches = FALSE;
     foreach ($elements as $element) {
       // SimpleXML objects need string casting all the time.
diff --git a/core/modules/system/src/Tests/Common/RenderTest.php b/core/modules/system/src/Tests/Common/RenderTest.php
index 6848dc9..ff487b8 100644
--- a/core/modules/system/src/Tests/Common/RenderTest.php
+++ b/core/modules/system/src/Tests/Common/RenderTest.php
@@ -654,9 +654,9 @@ function testDrupalRenderChildrenPostRenderCache() {
 
     $dom = Html::load($cached_element['#markup']);
     $xpath = new \DOMXPath($dom);
-    $parent = $xpath->query('//details[@class="form-wrapper" and @open="open"]/summary[@role="button" and @aria-expanded and text()="Parent"]')->length;
-    $child =  $xpath->query('//details[@class="form-wrapper" and @open="open"]/div[@class="details-wrapper"]/details[@class="form-wrapper" and @open="open"]/summary[@role="button" and @aria-expanded and text()="Child"]')->length;
-    $subchild = $xpath->query('//details[@class="form-wrapper" and @open="open"]/div[@class="details-wrapper"]/details[@class="form-wrapper" and @open="open"]/div [@class="details-wrapper" and text()="Subchild"]')->length;
+    $parent = $xpath->query($this->localizeXpath('//details[@class="form-wrapper" and @open="open"]/summary[@role="button" and @aria-expanded and text()="Parent"]'))->length;
+    $child =  $xpath->query($this->localizeXpath('//details[@class="form-wrapper" and @open="open"]/div[@class="details-wrapper"]/details[@class="form-wrapper" and @open="open"]/summary[@role="button" and @aria-expanded and text()="Child"]'))->length;
+    $subchild = $xpath->query($this->localizeXpath('//details[@class="form-wrapper" and @open="open"]/div[@class="details-wrapper"]/details[@class="form-wrapper" and @open="open"]/div[@class="details-wrapper" and text()="Subchild"]'))->length;
     $this->assertTrue($parent && $child && $subchild, 'The correct data is cached: the stored #markup is not affected by #post_render_cache callbacks.');
 
     // Remove markup because it's compared above in the xpath.
@@ -724,9 +724,9 @@ function testDrupalRenderChildrenPostRenderCache() {
 
     $dom = Html::load($cached_parent_element['#markup']);
     $xpath = new \DOMXPath($dom);
-    $parent = $xpath->query('//details[@class="form-wrapper" and @open="open"]/summary[@role="button" and @aria-expanded and text()="Parent"]')->length;
-    $child =  $xpath->query('//details[@class="form-wrapper" and @open="open"]/div[@class="details-wrapper"]/details[@class="form-wrapper" and @open="open"]/summary[@role="button" and @aria-expanded and text()="Child"]')->length;
-    $subchild = $xpath->query('//details[@class="form-wrapper" and @open="open"]/div[@class="details-wrapper"]/details[@class="form-wrapper" and @open="open"]/div [@class="details-wrapper" and text()="Subchild"]')->length;
+    $parent = $xpath->query($this->localizeXpath('//details[@class="form-wrapper" and @open="open"]/summary[@role="button" and @aria-expanded and text()="Parent"]'))->length;
+    $child =  $xpath->query($this->localizeXpath('//details[@class="form-wrapper" and @open="open"]/div[@class="details-wrapper"]/details[@class="form-wrapper" and @open="open"]/summary[@role="button" and @aria-expanded and text()="Child"]'))->length;
+    $subchild = $xpath->query($this->localizeXpath('//details[@class="form-wrapper" and @open="open"]/div[@class="details-wrapper"]/details[@class="form-wrapper" and @open="open"]/div[@class="details-wrapper" and text()="Subchild"]'))->length;
     $this->assertTrue($parent && $child && $subchild, 'The correct data is cached for the parent: the stored #markup is not affected by #post_render_cache callbacks.');
 
     // Remove markup because it's compared above in the xpath.
@@ -750,8 +750,8 @@ function testDrupalRenderChildrenPostRenderCache() {
 
     $dom = Html::load($cached_child_element['#markup']);
     $xpath = new \DOMXPath($dom);
-    $child =  $xpath->query('//details[@class="form-wrapper" and @open="open"]/summary[@role="button" and @aria-expanded and text()="Child"]')->length;
-    $subchild = $xpath->query('//details[@class="form-wrapper" and @open="open"]/div [@class="details-wrapper" and text()="Subchild"]')->length;
+    $child =  $xpath->query($this->localizeXpath('//details[@class="form-wrapper" and @open="open"]/summary[@role="button" and @aria-expanded and text()="Child"]'))->length;
+    $subchild = $xpath->query($this->localizeXpath('//details[@class="form-wrapper" and @open="open"]/div[@class="details-wrapper" and text()="Subchild"]'))->length;
     $this->assertTrue($child && $subchild, 'The correct data is cached for the child: the stored #markup is not affected by #post_render_cache callbacks.');
 
     // Remove markup because it's compared above in the xpath.
diff --git a/core/modules/system/src/Tests/Theme/FunctionsTest.php b/core/modules/system/src/Tests/Theme/FunctionsTest.php
index c1ad1c7..6683e9a 100644
--- a/core/modules/system/src/Tests/Theme/FunctionsTest.php
+++ b/core/modules/system/src/Tests/Theme/FunctionsTest.php
@@ -12,6 +12,7 @@
 use Drupal\Core\Session\UserSession;
 use Drupal\Core\Url;
 use Drupal\simpletest\WebTestBase;
+use Masterminds\HTML5;
 
 /**
  * Tests for common theme functions.
@@ -337,13 +338,14 @@ function testDrupalPreRenderLinks() {
       ),
     );
 
+    $html5 = new HTML5();
+
     // Start with a fresh copy of the base array, and try rendering the entire
     // thing. We expect a single <ul> with appropriate links contained within
     // it.
     $render_array = $base_array;
     $html = drupal_render($render_array);
-    $dom = new \DOMDocument();
-    $dom->loadHTML($html);
+    $dom = $html5->loadHTML($html);
     $this->assertEqual($dom->getElementsByTagName('ul')->length, 1, 'One "ul" tag found in the rendered HTML.');
     $list_elements = $dom->getElementsByTagName('li');
     $this->assertEqual($list_elements->length, 3, 'Three "li" tags found in the rendered HTML.');
@@ -360,16 +362,14 @@ function testDrupalPreRenderLinks() {
     $child_html = drupal_render($render_array['first_child']);
     $parent_html = drupal_render($render_array);
     // First check the child HTML.
-    $dom = new \DOMDocument();
-    $dom->loadHTML($child_html);
+    $dom = $html5->loadHTML($child_html);
     $this->assertEqual($dom->getElementsByTagName('ul')->length, 1, 'One "ul" tag found in the rendered child HTML.');
     $list_elements = $dom->getElementsByTagName('li');
     $this->assertEqual($list_elements->length, 2, 'Two "li" tags found in the rendered child HTML.');
     $this->assertEqual($list_elements->item(0)->nodeValue, 'Parent link copy', 'First expected link found.');
     $this->assertEqual($list_elements->item(1)->nodeValue, 'First child link', 'Second expected link found.');
     // Then check the parent HTML.
-    $dom = new \DOMDocument();
-    $dom->loadHTML($parent_html);
+    $dom = $html5->loadHTML($parent_html);
     $this->assertEqual($dom->getElementsByTagName('ul')->length, 1, 'One "ul" tag found in the rendered parent HTML.');
     $list_elements = $dom->getElementsByTagName('li');
     $this->assertEqual($list_elements->length, 2, 'Two "li" tags found in the rendered parent HTML.');
diff --git a/core/modules/system/tests/modules/form_test/src/Form/FormTestCheckboxesZeroForm.php b/core/modules/system/tests/modules/form_test/src/Form/FormTestCheckboxesZeroForm.php
index ccd752f..e7d0aa6 100644
--- a/core/modules/system/tests/modules/form_test/src/Form/FormTestCheckboxesZeroForm.php
+++ b/core/modules/system/tests/modules/form_test/src/Form/FormTestCheckboxesZeroForm.php
@@ -56,7 +56,7 @@ public function buildForm(array $form, FormStateInterface $form_state, $json = T
    * {@inheritdoc}
    */
   public function submitForm(array &$form, FormStateInterface $form_state) {
-    if ($form_state->has('json')) {
+    if ($form_state->get('json')) {
       $form_state->setResponse(new JsonResponse($form_state->getValues()));
     }
     else {
diff --git a/core/modules/views/src/Tests/Handler/FieldWebTest.php b/core/modules/views/src/Tests/Handler/FieldWebTest.php
index cd11a52..3124ae3 100644
--- a/core/modules/views/src/Tests/Handler/FieldWebTest.php
+++ b/core/modules/views/src/Tests/Handler/FieldWebTest.php
@@ -11,6 +11,7 @@
 use Drupal\Component\Utility\String;
 use Drupal\Component\Utility\UrlHelper;
 use Drupal\views\Views;
+use Masterminds\HTML5;
 
 /**
  * Tests fields from within a UI.
@@ -136,11 +137,9 @@ protected function assertNotSubString($haystack, $needle, $message = '', $group
    *   An array containing simplexml objects.
    */
   protected function parseContent($content) {
-    $htmlDom = new \DOMDocument();
-    @$htmlDom->loadHTML('<?xml encoding="UTF-8">' . $content);
-    $elements = simplexml_import_dom($htmlDom);
-
-    return $elements;
+    $html5 = new HTML5();
+    $dom = $html5->loadHTML($content);
+    return @simplexml_import_dom($dom);
   }
 
   /**
@@ -163,6 +162,14 @@ protected function parseContent($content) {
   protected function xpathContent($content, $xpath, array $arguments = array()) {
     if ($elements = $this->parseContent($content)) {
       $xpath = $this->buildXPathQuery($xpath, $arguments);
+
+      // Register the default namespace if it exists.
+      $namespaces = $elements->getDocNamespaces();
+      if (!empty($namespaces[''])) {
+        $xpath = $this->prefixXpath($xpath);
+        $elements->registerXPathNamespace('x', $namespaces['']);
+      }
+
       $result = $elements->xpath($xpath);
       // Some combinations of PHP / libxml versions return an empty array
       // instead of the documented FALSE. Forcefully convert any falsish values
diff --git a/core/modules/views/src/Tests/Plugin/StyleOpmlTest.php b/core/modules/views/src/Tests/Plugin/StyleOpmlTest.php
index 6580c0c..df008c5 100644
--- a/core/modules/views/src/Tests/Plugin/StyleOpmlTest.php
+++ b/core/modules/views/src/Tests/Plugin/StyleOpmlTest.php
@@ -60,7 +60,7 @@ public function testOpmlOutput() {
     $outline = $this->xpath('//outline[1]');
     $this->assertEqual($outline[0]['type'], 'rss', 'The correct type attribute is used for rss OPML.');
     $this->assertEqual($outline[0]['text'], $feed->label(), 'The correct text attribute is used for rss OPML.');
-    $this->assertEqual($outline[0]['xmlurl'], $feed->getUrl(), 'The correct xmlUrl attribute is used for rss OPML.');
+    $this->assertEqual($outline[0]['xmlUrl'], $feed->getUrl(), 'The correct xmlUrl attribute is used for rss OPML.');
 
     $view = $this->container->get('entity.manager')
       ->getStorage('view')
diff --git a/core/modules/views/src/Tests/Plugin/StyleTest.php b/core/modules/views/src/Tests/Plugin/StyleTest.php
index 957f8f8..21610c0 100644
--- a/core/modules/views/src/Tests/Plugin/StyleTest.php
+++ b/core/modules/views/src/Tests/Plugin/StyleTest.php
@@ -13,6 +13,7 @@
 use Drupal\views\Plugin\views\row\Fields;
 use Drupal\views\ResultRow;
 use Drupal\views_test_data\Plugin\views\style\StyleTest as StyleTestPlugin;
+use Masterminds\HTML5;
 
 /**
  * Tests general style functionality.
@@ -250,8 +251,8 @@ function testCustomRowClasses() {
    * Stores a view output in the elements.
    */
   protected function storeViewPreview($output) {
-    $htmlDom = new \DOMDocument();
-    @$htmlDom->loadHTML($output);
+    $html5 = new HTML5();
+    $htmlDom = $html5->loadHTML('<html><body>' . $output . '</body></html>');
     if ($htmlDom) {
       // It's much easier to work with simplexml than DOM, luckily enough
       // we can just simply import our DOM tree.
diff --git a/core/modules/views/src/Tests/Plugin/StyleTestBase.php b/core/modules/views/src/Tests/Plugin/StyleTestBase.php
index 8bc328c..b5f729c 100644
--- a/core/modules/views/src/Tests/Plugin/StyleTestBase.php
+++ b/core/modules/views/src/Tests/Plugin/StyleTestBase.php
@@ -8,6 +8,7 @@
 namespace Drupal\views\Tests\Plugin;
 
 use Drupal\views\Tests\ViewUnitTestBase;
+use Masterminds\HTML5;
 
 /**
  * Tests some general style plugin related functionality.
@@ -25,8 +26,8 @@
    * Stores a view output in the elements.
    */
   function storeViewPreview($output) {
-    $htmlDom = new \DOMDocument();
-    @$htmlDom->loadHTML($output);
+    $html5 = new HTML5();
+    $htmlDom = $html5->loadHTML('<html><body>' . $output . '</body></html>');
     if ($htmlDom) {
       // It's much easier to work with simplexml than DOM, luckily enough
       // we can just simply import our DOM tree.
diff --git a/core/tests/Drupal/Tests/Component/XpathHelper/LexerTest.php b/core/tests/Drupal/Tests/Component/XpathHelper/LexerTest.php
new file mode 100644
index 0000000..8470461
--- /dev/null
+++ b/core/tests/Drupal/Tests/Component/XpathHelper/LexerTest.php
@@ -0,0 +1,47 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Tests\Component\XpathHelper\LexerTest.
+ */
+
+namespace Drupal\Tests\Component\XpathHelper;
+
+use Drupal\Component\XpathHelper\Lexer;
+
+/**
+ * @covers \Drupal\Component\XpathHelper\Lexer
+ * @group XpathHelper
+ */
+class LexerTest extends \PHPUnit_Framework_TestCase {
+
+  /**
+   * @dataProvider providerLexer
+   * @param $expected
+   * @param $input
+   */
+  public function testLexer($expected, $input) {
+    $lexer = new Lexer();
+    $this->assertSame($input, $lexer->lex($expected));
+  }
+
+  public function providerLexer() {
+    return [
+      ['cat', ['cat']],
+      ['/cow/barn', ['/', 'cow', '/', 'barn']],
+      ['""', ['""']],
+      ['/cow/barn[@id = "asdfsaf"]', ['/', 'cow', '/', 'barn', '[', '@id', ' ', '=', ' ', '"asdfsaf"', ']']],
+      ['/cow/barn[@id=chair]', ['/', 'cow', '/', 'barn', '[', '@id', '=', 'chair', ']']],
+      ['/cow:asdf', ['/', 'cow', ':', 'asdf']],
+      ['@cow', ['@cow']],
+      ['starts-with(@id, "cat")', ['starts-with', '(', '@id' , ',', ' ', '"cat"', ')']],
+      ['starts-with(cat/dog/fire:breather, "cat")', ['starts-with', '(', 'cat', '/', 'dog', '/', 'fire' , ':', 'breather', ',', ' ', '"cat"', ')']],
+      ['child::book', ['child', '::', 'book']],
+      ["//a[@href='javascript:void(0)']", ['//', 'a', '[', '@href', '=', "'javascript:void(0)'", ']']],
+      ['1+1', ['1', '+', '1']],
+      ['//a[@id="id"and 1]', ['//', 'a', '[', '@id', '=', '"id"', 'and', ' ', '1', ']']],
+      ['0', ['0']],
+    ];
+  }
+
+}
diff --git a/core/tests/Drupal/Tests/Component/XpathHelper/NamespacerTest.php b/core/tests/Drupal/Tests/Component/XpathHelper/NamespacerTest.php
new file mode 100644
index 0000000..c55c7d4
--- /dev/null
+++ b/core/tests/Drupal/Tests/Component/XpathHelper/NamespacerTest.php
@@ -0,0 +1,100 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Tests\Component\XpathHelper\NamespacerTest.
+ */
+
+namespace Drupal\Tests\Component\XpathHelper;
+
+use Drupal\Component\XpathHelper\Namespacer;
+
+/**
+ * @covers \Drupal\Component\XpathHelper\Namespacer
+ * @group XpathHelper
+ */
+class NamespacerTest extends \PHPUnit_Framework_TestCase {
+
+  /**
+   * @dataProvider providerNamespacer
+   * @param $expected
+   * @param $input
+   */
+  public function testNamespacer($expected, $input) {
+    $this->assertSame($input, Namespacer::prefix($expected));
+  }
+
+  public function testCache() {
+    $this->assertSame('x:a', Namespacer::prefix('a'));
+
+    $this->assertSame('*[local-name() = "a"]', Namespacer::localize('a'));
+  }
+
+  public function providerNamespacer() {
+    $tests = [
+      ['cow', 'x:cow'],
+      ['/cow/barn', '/x:cow/x:barn'],
+      ['/cow/barn[@id = "asdfsaf"]', '/x:cow/x:barn[@id = "asdfsaf"]'],
+      ['/cow/barn [@id = "asdfsaf"]', '/x:cow/x:barn [@id = "asdfsaf"]'],
+      ['/cow/barn[@id=chair]', '/x:cow/x:barn[@id=x:chair]'],
+      ['/cow:asdf', '/cow:asdf'],
+      ['@cow', '@cow'],
+      ['starts-with(@id, "cat")', 'starts-with(@id, "cat")'],
+      ['starts-with(cat/dog/fire:breather, "cat")', 'starts-with(x:cat/x:dog/fire:breather, "cat")'],
+      ['//state[@id = ../city[name="CityName"]/state_id]/name', '//x:state[@id = ../x:city[x:name="CityName"]/x:state_id]/x:name'],
+      ['attribute::lang', 'attribute::lang'],
+      ['attribute:: lang', 'attribute:: lang'],
+      ['attribute ::lang', 'attribute ::lang'],
+      ['attribute :: lang', 'attribute :: lang'],
+      ['child::book', 'child::x:book'],
+      ['child :: book', 'child :: x:book'],
+      ['child::*', 'child::*'],
+      ['child:: *', 'child:: *'],
+      ['child ::*', 'child ::*'],
+      ['child :: *', 'child :: *'],
+      ['child::text()', 'child::text()'],
+      ['child::text   ()', 'child::text   ()'],
+      ['ancestor-or-self::book', 'ancestor-or-self::x:book'],
+      ['child::*/child::price', 'child::*/child::x:price'],
+      ["/asdfasfd[@id = 'a' or @id='b']", "/x:asdfasfd[@id = 'a' or @id='b']"],
+      ["id('yui-gen2')/x:div[3]/x:div/x:a[1]", "id('yui-gen2')/x:div[3]/x:div/x:a[1]"],
+      ["/descendant::a[@class='buttonCheckout']", "/descendant::x:a[@class='buttonCheckout']"],
+      ["//a[@href='javascript:void(0)']", "//x:a[@href='javascript:void(0)']"],
+      ['//*/@attribute', '//*/@attribute'],
+      ['/descendant::*[attribute::attribute]', '/descendant::*[attribute::attribute]'],
+      ['//Event[not(System/Level = preceding::Level) or not(System/Task = preceding::Task)]', '//x:Event[not(x:System/x:Level = preceding::x:Level) or not(x:System/x:Task = preceding::x:Task)]'],
+      ["section[@type='cover']/line/@page", "x:section[@type='cover']/x:line/@page"],
+      ['/articles/article/*[name()="title" or name()="short"]', '/x:articles/x:article/*[name()="title" or name()="short"]'],
+      ["/*/article[@id='2']/*[self::title or self::short]", "/*/x:article[@id='2']/*[self::x:title or self::x:short]"],
+      ['not(/asdfasfd/asdfasf//asdfasdf) | /asdfasf/sadfasf/@asdf', 'not(/x:asdfasfd/x:asdfasf//x:asdfasdf) | /x:asdfasf/x:sadfasf/@asdf'],
+      ['Ülküdak', 'x:Ülküdak'],
+      ['//textarea[@name="style[type]"]|//input[@name="style[type]"]|//select[@name="style[type]"]', '//x:textarea[@name="style[type]"]|//x:input[@name="style[type]"]|//x:select[@name="style[type]"]'],
+      ['//a[@id="id"and 1]', '//x:a[@id="id"and 1]'],
+      ['//*[@id and@class]', '//*[@id and@class]'],
+      ['/or', '/x:or'],
+      ['//and', '//x:and'],
+      ['div', 'x:div'],
+      ['a-1', 'x:a-1'],
+      ['//element [contains(@id, "1234")and contains(@id, 345)]', '//x:element [contains(@id, "1234")and contains(@id, 345)]'],
+      ['following-sibling::div', 'following-sibling::x:div'],
+      ['//  div  /  a  /  @href', '//  x:div  /  x:a  /  @href'],
+      ['a[contains(div, div)', 'x:a[contains(x:div, x:div)'],
+    ];
+
+    // Math related.
+    foreach (['+', '-', '*', '=', '!=', '<', '>', '<=', '>='] as $op) {
+      $tests[] = ["1{$op}2", "1{$op}2"];
+      $tests[] = ["1 {$op}2", "1 {$op}2"];
+      $tests[] = ["1{$op} 2", "1{$op} 2"];
+      $tests[] = ["1 {$op} 2", "1 {$op} 2"];
+    }
+
+    foreach (['and', 'or', 'mod', 'div'] as $op) {
+      $tests[] = ["1{$op} 2", "1{$op} 2"];
+      $tests[] = ["1 {$op} 2", "1 {$op} 2"];
+    }
+
+    return $tests;
+  }
+
+}
diff --git a/core/vendor/composer/autoload_psr4.php b/core/vendor/composer/autoload_psr4.php
index 8b6150b..a75b107 100644
--- a/core/vendor/composer/autoload_psr4.php
+++ b/core/vendor/composer/autoload_psr4.php
@@ -8,6 +8,7 @@
 return array(
     'Symfony\\Cmf\\Component\\Routing\\' => array($vendorDir . '/symfony-cmf/routing'),
     'React\\Promise\\' => array($vendorDir . '/react/promise/src'),
+    'Masterminds\\' => array($vendorDir . '/masterminds/html5/src'),
     'GuzzleHttp\\Stream\\' => array($vendorDir . '/guzzlehttp/streams/src'),
     'GuzzleHttp\\Ring\\' => array($vendorDir . '/guzzlehttp/ringphp/src'),
     'GuzzleHttp\\' => array($vendorDir . '/guzzlehttp/guzzle/src'),
diff --git a/core/vendor/composer/installed.json b/core/vendor/composer/installed.json
index 6104e35..a047894 100644
--- a/core/vendor/composer/installed.json
+++ b/core/vendor/composer/installed.json
@@ -2674,5 +2674,72 @@
             "feed",
             "zf2"
         ]
+    },
+    {
+        "name": "masterminds/html5",
+        "version": "dev-master",
+        "version_normalized": "9999999-dev",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/Masterminds/html5-php.git",
+            "reference": "b39dd885966dea2d3d33509af505f4ecef2f6343"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/b39dd885966dea2d3d33509af505f4ecef2f6343",
+            "reference": "b39dd885966dea2d3d33509af505f4ecef2f6343",
+            "shasum": ""
+        },
+        "require": {
+            "ext-libxml": "*",
+            "php": ">=5.3.0"
+        },
+        "require-dev": {
+            "phpunit/phpunit": "4.*",
+            "sami/sami": "~2.0",
+            "satooshi/php-coveralls": "0.6.*"
+        },
+        "time": "2014-12-02 02:51:14",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "2.0-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "psr-4": {
+                "Masterminds\\": "src"
+            }
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "Matt Butcher",
+                "email": "technosophos@gmail.com"
+            },
+            {
+                "name": "Asmir Mustafic",
+                "email": "goetas@gmail.com"
+            },
+            {
+                "name": "Matt Farina",
+                "email": "matt@mattfarina.com"
+            }
+        ],
+        "description": "An HTML5 parser and serializer.",
+        "homepage": "http://masterminds.github.io/html5-php",
+        "keywords": [
+            "HTML5",
+            "dom",
+            "html",
+            "parser",
+            "querypath",
+            "serializer",
+            "xml"
+        ]
     }
 ]
