diff --git a/lib/SimpleSAML/Metadata/SAMLParser.php b/lib/SimpleSAML/Metadata/SAMLParser.php
index 6608dbadfea2a4f54d5468b9cd582a4ef02b571d..fc84e911dc3427bbed8a34512c0776217df7c561 100644
--- a/lib/SimpleSAML/Metadata/SAMLParser.php
+++ b/lib/SimpleSAML/Metadata/SAMLParser.php
@@ -30,34 +30,6 @@ class SimpleSAML_Metadata_SAMLParser {
 		);
 
 
-	/**
-	 * This is the binding used to send authentication requests in SAML 1.x.
-	 */
-	const SAML_1x_AUTHN_REQUEST = 'urn:mace:shibboleth:1.0:profiles:AuthnRequest';
-
-	/**
-	 * This is the binding used for browser post in SAML 1.x.
-	 */
-	const SAML_1X_POST_BINDING = 'urn:oasis:names:tc:SAML:1.0:profiles:browser-post';
-
-	/**
-	 * This is the SAML 1.0 SOAP binding.
-	 */
-	const SAML_1X_SOAP_BINDING = 'urn:oasis:names:tc:SAML:1.0:bindings:SOAP-binding';
-
-
-	/**
-	 * This is the binding used for HTTP-POST in SAML 2.0.
-	 */
-	const SAML_20_POST_BINDING = 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST';
-
-
-	/**
-	 * This is the binding used for HTTP-REDIRECT in SAML 2.0.
-	 */
-	const SAML_20_REDIRECT_BINDING = 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect';
-
-
 	/**
 	 * This is the entity id we find in the metadata.
 	 */
@@ -120,11 +92,11 @@ class SimpleSAML_Metadata_SAMLParser {
 
 
 	/**
-	 * This is an array of SimpleSAML_XML_Validator classes. If this EntityDescriptor is signed, one of the
-	 * validators should be able to verify the fingerprint of the certificate which was used to sign
-	 * this EntityDescriptor.
+	 * This is an array of elements that may be sued to validate this element.
+	 *
+	 * @var array
 	 */
-	private $validator = array();
+	private $validators = array();
 
 
 	/**
@@ -136,81 +108,47 @@ class SimpleSAML_Metadata_SAMLParser {
 	/**
 	 * This is the constructor for the SAMLParser class.
 	 *
-	 * @param $entityElement The DOMElement which represents the EntityDescriptor-element.
-	 * @param $entitiesValidator  A Validator instance for a signature element in the EntitiesDescriptor,
-	 *                            or NULL if this EntityDescriptor isn't a child of an EntitiesDescriptor
-	 *                            with a Signature element.
-	 * @param int|NULL $expireTime  The unix timestamp for when this entity should expire, or NULL if unknwon.
+	 * @param SAML2_XML_md_EntityDescriptor $entityElement  The EntityDescriptor.
+	 * @param int|NULL $maxExpireTime  The unix timestamp for when this entity should expire, or NULL if unknwon.
+	 * @param array $validators  An array of parent elements that may validate this element.
 	 */
-	private function __construct(DOMElement $entityElement,	$entitiesValidator, $expireTime) {
-		assert('is_null($entitiesValidator) || $entitiesValidator instanceof SimpleSAML_XML_Validator');
-		assert('is_null($expireTime) || is_int($expireTime)');
+	private function __construct(SAML2_XML_md_EntityDescriptor $entityElement, $maxExpireTime, array $validators = array()) {
+		assert('is_null($maxExpireTime) || is_int($maxExpireTime)');
 
 		$this->spDescriptors = array();
 		$this->idpDescriptors = array();
 
-		$tmpDoc = new DOMDocument();
-		$tmpDoc->appendChild($tmpDoc->importNode($entityElement, TRUE));
-		$this->entityDescriptor = base64_encode($tmpDoc->saveXML());
+		$e = $entityElement->toXML();
+		$e = $e->ownerDocument->saveXML($e);
+		$this->entityDescriptor = base64_encode($e);
+		$this->entityId = $entityElement->entityID;
 
-		/* Extract the entity id from the EntityDescriptor element. This is a required
-		 * attribute, so we throw an exception if it isn't found.
-		 */
-		if(!$entityElement->hasAttribute('entityID')) {
-			throw new Exception('EntityDescriptor missing required entityID attribute.');
-		}
-		$this->entityId = $entityElement->getAttribute('entityID');
-
-		if ($expireTime === NULL) {
-			/* No expiry time defined by a parent element. Check if this element defines
-			 * one.
-			 */
-			$expireTime = self::getExpireTime($entityElement);
-		}
+		$expireTime = self::getExpireTime($entityElement, $maxExpireTime);
 
+		$this->validators = $validators;
+		$this->validators[] = $entityElement;
 
-		/* Check if the Signature element from the EntitiesDescriptor can be used to verify this
-		 * EntityDescriptor, and add it to the list of validators if it is.
-		 */
-		if($entitiesValidator !== NULL && $entitiesValidator->isNodeValidated($entityElement)) {
-			$this->validator[] = $entitiesValidator;
-		}
 
 		/* Process Extensions element, if it exists. */
 		$ext = self::processExtensions($entityElement);
 		$this->scopes = $ext['scopes'];
 		$this->tags = $ext['tags'];
 
-		/* Look over the child nodes for any known element types. */
-		for($i = 0; $i < $entityElement->childNodes->length; $i++) {
-			$child = $entityElement->childNodes->item($i);
+		/* Look over the RoleDescriptors. */
+		foreach ($entityElement->RoleDescriptor as $child) {
 
-			// Unless the child is a DOMElement, skip.
-			if ( !($child instanceof DOMelement) ) continue;
-
-			if(SimpleSAML_Utilities::isDOMElementOfType($child, 'Signature', '@ds') === TRUE) {
-				$this->processSignature($child);
-			}
-
-			if(SimpleSAML_Utilities::isDOMElementOfType($child, 'SPSSODescriptor', '@md') === TRUE) {
+			if ($child instanceof SAML2_XML_md_SPSSODescriptor) {
 				$this->processSPSSODescriptor($child, $expireTime);
-			}
-
-			if(SimpleSAML_Utilities::isDOMElementOfType($child, 'IDPSSODescriptor', '@md') === TRUE) {
+			} elseif ($child instanceof SAML2_XML_md_IDPSSODescriptor) {
 				$this->processIDPSSODescriptor($child, $expireTime);
-			}
-
-			if(SimpleSAML_Utilities::isDOMElementOfType($child, 'AttributeAuthorityDescriptor', '@md') === TRUE) {
+			} elseif ($child instanceof SAML2_XML_md_AttributeAuthorityDescriptor) {
 				$this->processAttributeAuthorityDescriptor($child, $expireTime);
 			}
-
-			if(SimpleSAML_Utilities::isDOMElementOfType($child, 'Organization', '@md') === TRUE) {
-				$this->processOrganization($child);
-			}
-
 		}
 
-
+		if ($entityElement->Organization) {
+			$this->processOrganization($entityElement->Organization);
+		}
 	}
 
 
@@ -328,48 +266,55 @@ class SimpleSAML_Metadata_SAMLParser {
 	 * This function parses a DOMElement which represents either an EntityDescriptor element or an
 	 * EntitiesDescriptor element. It will return an associative array of SAMLParser instances in both cases.
 	 *
-	 * @param $element  The DOMElement which contains the EntityDescriptor element or the EntitiesDescriptor
-	 *                  element.
+	 * @param DOMElement|NULL $element  The DOMElement which contains the EntityDescriptor element or the EntitiesDescriptor element.
 	 * @return An associative array of SAMLParser instances. The key of the array will be the entity id.
 	 */
-	public static function parseDescriptorsElement($element) {
+	public static function parseDescriptorsElement(DOMElement $element = NULL) {
 
 		if($element === NULL) {
 			throw new Exception('Document was empty.');
 		}
 
 		assert('$element instanceof DOMElement');
-		
-		$entitiesValidator = NULL;
 
 		if(SimpleSAML_Utilities::isDOMElementOfType($element, 'EntityDescriptor', '@md') === TRUE) {
-			$elements = array($element);
-			$expireTime = NULL;
+			return self::processDescriptorsElement(new SAML2_XML_md_EntityDescriptor($element));
 		} elseif(SimpleSAML_Utilities::isDOMElementOfType($element, 'EntitiesDescriptor', '@md') === TRUE) {
-
-			/* Check if there is a signature element in the EntitiesDescriptor. */
-			if(count(SimpleSAML_Utilities::getDOMChildren($element, 'Signature', '@ds')) > 0) {
-				try {
-					$entitiesValidator = new SimpleSAML_XML_Validator($element, 'ID');
-				} catch(Exception $e) {
-					SimpleSAML_Logger::warning('SAMLParser: Error creating XML Signature validator for XML document: ' . 
-						$e->getMessage());
-					$entitiesValidator = NULL;
-				}
-			}
-
-			$expireTime = self::getExpireTime($element);
-
-			$elements = SimpleSAML_Utilities::getDOMChildren($element, 'EntityDescriptor', '@md');
+			return self::processDescriptorsElement(new SAML2_XML_md_EntitiesDescriptor($element));
 		} else {
 			throw new Exception('Unexpected root node: [' . $element->namespaceURI . ']:' .
 				$element->localName);
 		}
 
+		return $ret;
+	}
+
+
+	/**
+	 *
+	 * @param SAML2_XML_md_EntityDescriptor|SAML2_XML_md_EntitiesDescriptor $element  The element we should process.
+	 * @param int|NULL $maxExpireTime  The maximum expiration time of the entitites.
+	 * @param array $validators  The parent-elements that may be signed.
+	 * @return array  Array of SAMLParser instances.
+	 */
+	private static function processDescriptorsElement($element, $maxExpireTime = NULL, array $validators = array()) {
+		assert('is_null($maxExpireTime) || is_int($maxExpireTime)');
+
+		if ($element instanceof SAML2_XML_md_EntityDescriptor) {
+			$ret = new SimpleSAML_Metadata_SAMLParser($element, $maxExpireTime, $validators);
+			return array($ret->getEntityId() => $ret);
+		}
+
+		assert('$element instanceof SAML2_XML_md_EntitiesDescriptor');
+
+
+		$expTime = self::getExpireTime($element, $maxExpireTime);
+
+		$validators[] = $element;
+
 		$ret = array();
-		foreach($elements as $e) {
-			$entity = new SimpleSAML_Metadata_SAMLParser($e, $entitiesValidator, $expireTime);
-			$ret[$entity->getEntityId()] = $entity;
+		foreach ($element->children as $child) {
+			$ret += self::processDescriptorsElement($child, $expTime, $validators);
 		}
 
 		return $ret;
@@ -385,42 +330,29 @@ class SimpleSAML_Metadata_SAMLParser {
 	 * If both the 'cacheDuration' and 'validUntil' attributes are present, the shorter of them
 	 * will be returned.
 	 *
-	 * @param DOMElement $element  The element we should determine the expiry time of.
+	 * @param mixed $element  The element we should determine the expiry time of.
+	 * @param int|NULL $maxExpireTime  The maximum expiration time.
 	 * @return int  The unix timestamp for when the element should expire. Will be NULL if no
 	 *              limit is set for the element.
 	 */
-	private static function getExpireTime(DOMElement $element) {
+	private static function getExpireTime($element, $maxExpireTime) {
 
-		if ($element->hasAttribute('cacheDuration')) {
-			$cacheDuration = $element->getAttribute('cacheDuration');
-			$cacheDuration = SimpleSAML_Utilities::parseDuration($cacheDuration, time());
-		} else {
-			$cacheDuration = NULL;
-		}
-
-		if ($element->hasAttribute('validUntil')) {
-			$validUntil = $element->getAttribute('validUntil');
-			$validUntil = SimpleSAML_Utilities::parseSAML2Time($validUntil);
+		if ($element->cacheDuration !== NULL) {
+			$expire = SimpleSAML_Utilities::parseDuration($element->cacheDuration, time());
+			if ($maxExpireTime !== NULL && $maxExpireTime < $expire) {
+				$expire = $maxExpireTime;
+			}
 		} else {
-			$validUntil = NULL;
+			$expire = $maxExpireTime;
 		}
 
-		if ($cacheDuration !== NULL && $validUntil !== NULL) {
-			/* Both are given. Return the shortest. */
-
-			if($cacheDuration < $validUntil) {
-				return $cacheDuration;
-			} else {
-				return $validUntil;
+		if ($element->validUntil !== NULL) {
+			if ($expire === NULL || $expire > $element->validUntil) {
+				$expire = $element->validUntil;
 			}
-
-		} elseif ($cacheDuration !== NULL) {
-			return $cacheDuration;
-		} elseif ($validUntil !== NULL) {
-			return $validUntil;
-		} else {
-			return NULL;
 		}
+
+		return $expire;
 	}
 
 
@@ -803,23 +735,17 @@ class SimpleSAML_Metadata_SAMLParser {
          * - 'expire': Timestamp for when this descriptor expires.
 	 * - 'keys': Array of associative arrays with the elements from parseKeyDescriptor.
 	 *
-	 * @param DOMElement $element  The element we should extract metadata from.
+	 * @param SAML2_XML_md_RoleDescriptor $element  The element we should extract metadata from.
 	 * @param int|NULL $expireTime  The unix timestamp for when this element should expire, or
 	 *                              NULL if unknwon.
 	 * @return Associative array with metadata we have extracted from this element.
 	 */
-	private static function parseRoleDescriptorType(DOMElement $element, $expireTime) {
+	private static function parseRoleDescriptorType(SAML2_XML_md_RoleDescriptor $element, $expireTime) {
 		assert('is_null($expireTime) || is_int($expireTime)');
 
 		$ret = array();
 
-		if ($expireTime === NULL) {
-			/* No expiry time defined by a parent element. Check if this element defines
-			 * one.
-			 */
-			$expireTime = self::getExpireTime($element);
-		}
-
+		$expireTime = self::getExpireTime($element, $expireTime);
 
 		if ($expireTime !== NULL) {
 			/* We have got an expire timestamp, either from this element, or one of the
@@ -828,12 +754,11 @@ class SimpleSAML_Metadata_SAMLParser {
 			$ret['expire'] = $expireTime;
 		}
 
-		$ret['protocols'] = self::getSupportedProtocols($element);
+		$ret['protocols'] = $element->protocolSupportEnumeration;
 
 		/* Process KeyDescriptor elements. */
 		$ret['keys'] = array();
-		$keys = SimpleSAML_Utilities::getDOMChildren($element, 'KeyDescriptor', '@md');
-		foreach($keys as $kd) {
+		foreach ($element->KeyDescriptor as $kd) {
 			$key = self::parseKeyDescriptor($kd);
 			if($key !== NULL) {
 				$ret['keys'][] = $key;
@@ -858,30 +783,25 @@ class SimpleSAML_Metadata_SAMLParser {
 	 * - 'nameIDFormats': The NameIDFormats supported by this SSODescriptor. This may be an empty array.
 	 * - 'keys': Array of associative arrays with the elements from parseKeyDescriptor:
 	 *
-	 * @param $element The element we should extract metadata from.
+	 * @param SAML2_XML_md_SSODescriptorType $element The element we should extract metadata from.
 	 * @param int|NULL $expireTime  The unix timestamp for when this element should expire, or
 	 *                              NULL if unknwon.
 	 * @return Associative array with metadata we have extracted from this element.
 	 */
-	private static function parseSSODescriptor($element, $expireTime) {
-		assert('$element instanceof DOMElement');
+	private static function parseSSODescriptor(SAML2_XML_md_SSODescriptorType $element, $expireTime) {
 		assert('is_null($expireTime) || is_int($expireTime)');
 
 		$sd = self::parseRoleDescriptorType($element, $expireTime);
 
 		/* Find all SingleLogoutService elements. */
-		$sd['SingleLogoutService'] = self::extractEndpoints($element, 'SingleLogoutService', FALSE);
+		$sd['SingleLogoutService'] = self::extractEndpoints($element->SingleLogoutService);
 
 		/* Find all ArtifactResolutionService elements. */
-		$sd['ArtifactResolutionService'] = self::extractEndpoints($element, 'ArtifactResolutionService', TRUE);
+		$sd['ArtifactResolutionService'] = self::extractEndpoints($element->ArtifactResolutionService);
 
 
 		/* Process NameIDFormat elements. */
-		$sd['nameIDFormats'] = array();
-		$nif = SimpleSAML_Utilities::getDOMChildren($element, 'NameIDFormat', '@md');
-		if(count($nif) > 0) {
-			$sd['nameIDFormats'][] = self::parseNameIDFormat($nif[0]);
-		}
+		$sd['nameIDFormats'] = $element->NameIDFormat;
 
 		return $sd;
 	}
@@ -890,25 +810,23 @@ class SimpleSAML_Metadata_SAMLParser {
 	/**
 	 * This function extracts metadata from a SPSSODescriptor element.
 	 *
-	 * @param $element The element which should be parsed.
+	 * @param SAML2_XML_md_SPSSODescriptor $element The element which should be parsed.
 	 * @param int|NULL $expireTime  The unix timestamp for when this element should expire, or
 	 *                              NULL if unknwon.
 	 */
-	private function processSPSSODescriptor($element, $expireTime) {
-		assert('$element instanceof DOMElement');
+	private function processSPSSODescriptor(SAML2_XML_md_SPSSODescriptor $element, $expireTime) {
 		assert('is_null($expireTime) || is_int($expireTime)');
 
 		$sp = self::parseSSODescriptor($element, $expireTime);
 
 		/* Find all AssertionConsumerService elements. */
-		$sp['AssertionConsumerService'] = self::extractEndpoints($element, 'AssertionConsumerService', TRUE);
+		$sp['AssertionConsumerService'] = self::extractEndpoints($element->AssertionConsumerService);
 
 		/* Find all the attributes and SP name... */
-		#$sp['attributes'] = array();
-		$attcs = SimpleSAML_Utilities::getDOMChildren($element, 'AttributeConsumingService', '@md');
+		$attcs = $element->AttributeConsumingService;
 		if (count($attcs) > 0) {
 			self::parseAttributeConsumerService($attcs[0], $sp);
-		}	
+		}
 
 		$this->spDescriptors[] = $sp;
 	}
@@ -917,20 +835,19 @@ class SimpleSAML_Metadata_SAMLParser {
 	/**
 	 * This function extracts metadata from a IDPSSODescriptor element.
 	 *
-	 * @param $element The element which should be parsed.
+	 * @param SAML2_XML_md_IDPSSODescriptor $element The element which should be parsed.
 	 * @param int|NULL $expireTime  The unix timestamp for when this element should expire, or
 	 *                              NULL if unknwon.
 	 */
-	private function processIDPSSODescriptor($element, $expireTime) {
-		assert('$element instanceof DOMElement');
+	private function processIDPSSODescriptor(SAML2_XML_md_IDPSSODescriptor $element, $expireTime) {
 		assert('is_null($expireTime) || is_int($expireTime)');
 
 		$idp = self::parseSSODescriptor($element, $expireTime);
 
 		/* Find all SingleSignOnService elements. */
-		$idp['SingleSignOnService'] = self::extractEndpoints($element, 'SingleSignOnService', FALSE);
+		$idp['SingleSignOnService'] = self::extractEndpoints($element->SingleSignOnService);
 
-		if ($element->getAttribute('WantAuthnRequestsSigned') === 'true') {
+		if ($element->WantAuthnRequestsSigned) {
 			$idp['WantAuthnRequestsSigned'] = TRUE;
 		} else {
 			$idp['WantAuthnRequestsSigned'] = FALSE;
@@ -943,23 +860,20 @@ class SimpleSAML_Metadata_SAMLParser {
 	/**
 	 * This function extracts metadata from a AttributeAuthorityDescriptor element.
 	 *
-	 * @param DOMElement $element The element which should be parsed.
+	 * @param SAML2_XML_md_AttributeAuthorityDescriptor $element The element which should be parsed.
 	 * @param int|NULL $expireTime  The unix timestamp for when this element should expire, or
 	 *                              NULL if unknwon.
 	 */
-	private function processAttributeAuthorityDescriptor(DOMElement $element, $expireTime) {
+	private function processAttributeAuthorityDescriptor(SAML2_XML_md_AttributeAuthorityDescriptor $element, $expireTime) {
 		assert('is_null($expireTime) || is_int($expireTime)');
 
 		$aad = self::parseRoleDescriptorType($element, $expireTime);
 		$aad['entityid'] = $this->entityId;
 		$aad['metadata-set'] = 'attributeauthority-remote';
 
-		$aad['AttributeService'] = self::extractEndpoints($element, 'AttributeService', FALSE);
-		$aad['AssertionIDRequestService'] = self::extractEndpoints($element, 'AssertionIDRequestService', FALSE);
-		$aad['NameIDFormat'] = array_map(
-			array('SimpleSAML_Utilities', 'getDOMText'),
-			SimpleSAML_Utilities::getDOMChildren($element, 'NameIDFormat', '@md')
-		);
+		$aad['AttributeService'] = self::extractEndpoints($element->AttributeService);
+		$aad['AssertionIDRequestService'] = self::extractEndpoints($element->AssertionIDRequestService);
+		$aad['NameIDFormat'] = $element->NameIDFormat;
 
 		$this->attributeAuthorityDescriptors[] = $aad;
 	}
@@ -968,41 +882,40 @@ class SimpleSAML_Metadata_SAMLParser {
 	/**
 	 * Parse an Extensions element.
 	 *
-	 * @param DOMElement $element  The DOMElement which contains the Extensions element.
+	 * @param mixed $element  The element which contains the Extensions element.
 	 */
-	private static function processExtensions(DOMElement $element) {
+	private static function processExtensions($element) {
 
 		$ret = array(
 			'scopes' => array(),
 			'tags' => array(),
 		);
 
-		$extensions = SimpleSAML_Utilities::getDOMChildren($element, 'Extensions', '@md');
-		if (empty($extensions)) {
-			/* No extension element. */
-			return $ret;
-		}
-		$element = $extensions[0];
+		foreach ($element->Extensions as $e) {
 
-		/* See: https://spaces.internet2.edu/display/SHIB/ShibbolethMetadataProfile */
-		foreach (SimpleSAML_Utilities::getDOMChildren($element, 'Scope', '@shibmd') as $scope) {
-			$scope = SimpleSAML_Utilities::getDOMText($scope);
-			if (!empty($scope)) {
-				$ret['scopes'][] = $scope;
+			if ($e instanceof SAML2_XML_shibmd_Scope) {
+				$ret['scopes'][] = $e->scope;
+				continue;
 			}
-		}
 
-		foreach (SimpleSAML_Utilities::getDOMChildren($element, 'Attribute', '@saml2') as $attribute) {
-			$name = $attribute->getAttribute('Name');
-			$values = array_map(
-				array('SimpleSAML_Utilities', 'getDOMText'),
-				SimpleSAML_Utilities::getDOMChildren($attribute, 'AttributeValue', '@saml2')
-			);
-
-			if ($name === 'tags') {
-				foreach ($values as $tagname) {
-					if (!empty($tagname)) {
-						$ret['tags'][] = $tagname;
+			if (!($e instanceof SAML2_XML_Chunk)) {
+				continue;
+			}
+
+			if ($e->localName === 'Attribute' && $e->namespaceURI === SAML2_Const::NS_SAML) {
+				$attribute = $e->getXML();
+
+				$name = $attribute->getAttribute('Name');
+				$values = array_map(
+					array('SimpleSAML_Utilities', 'getDOMText'),
+					SimpleSAML_Utilities::getDOMChildren($attribute, 'AttributeValue', '@saml2')
+				);
+
+				if ($name === 'tags') {
+					foreach ($values as $tagname) {
+						if (!empty($tagname)) {
+							$ret['tags'][] = $tagname;
+						}
 					}
 				}
 			}
@@ -1015,90 +928,33 @@ class SimpleSAML_Metadata_SAMLParser {
 	/**
 	 * Parse and process a Organization element.
 	 *
-	 * @param $element  The DOMElement which represents the Organization element.
+	 * @param SAML2_XML_md_Organization $element  The Organization element.
 	 */
-	private function processOrganization($element) {
-		assert('$element instanceof DOMElement');
-
-		for($i = 0; $i < $element->childNodes->length; $i++) {
-			$child = $element->childNodes->item($i);
-
-			/* Skip text nodes. */
-			if($child instanceof DOMText) {
-				continue;
-			}
-
-			/* Determine the type. */
-			if(SimpleSAML_Utilities::isDOMElementOfType($child, 'OrganizationName', '@md')) {
-				$type = 'organizationName';
-			} elseif(SimpleSAML_Utilities::isDOMElementOfType($child, 'OrganizationDisplayName', '@md')) {
-				$type = 'organizationDisplayName';
-			} elseif(SimpleSAML_Utilities::isDOMElementOfType($child, 'OrganizationURL', '@md')) {
-				$type = 'organizationURL';
-			} else {
-				/* Skip unknown/unhandled elements. */
-				continue;
-			}
-
-			/* Extract the text. */
-			$text = SimpleSAML_Utilities::getDOMText($child);
-
-			/* Skip nodes without text. */
-			if(empty($text)) {
-				continue;
-			}
+	private function processOrganization(SAML2_XML_md_Organization $element) {
 
-			/* Find the language of the text. This should be stored in the xml:lang attribute. */
-			$language = $child->getAttributeNS('http://www.w3.org/XML/1998/namespace', 'lang');
-			//$language = $child->getAttributeNS('xml', 'lang');
-			if(empty($language)) {
-				/* No language given, assume 'en'. */
-				$language = 'en';
-			}
-
-			/* Add the result to the appropriate list. */
-			if($type === 'organizationName') {
-				$this->organizationName[$language] = $text;
-			} elseif($type === 'organizationDisplayName') {
-				$this->organizationDisplayName[$language] = $text;
-			} elseif($type === 'organizationURL') {
-				$this->organizationURL[$language] = $text;
-			}
-		}
+		$this->organizationName = $element->OrganizationName;
+		$this->organizationDisplayName = $element->OrganizationDisplayName;
+		$this->organizationURL = $element->OrganizationURL;
 	}
 
 
 	/**
 	 * This function parses AttributeConsumerService elements.
 	 */
-	private static function parseAttributeConsumerService($element, &$sp) {
-		assert('$element instanceof DOMElement');
+	private static function parseAttributeConsumerService(SAML2_XML_md_AttributeConsumingService $element, &$sp) {
 		assert('is_array($sp)');
-				
-		$elements = SimpleSAML_Utilities::getDOMChildren($element, 'ServiceName', '@md');
-		foreach($elements AS $child) {
-			$language = $child->getAttributeNS('http://www.w3.org/XML/1998/namespace', 'lang');
-			if(empty($language)) $language = 'en';
-			$sp['name'][$language] = SimpleSAML_Utilities::getDOMText($child);
-		}
-		
-		$elements = SimpleSAML_Utilities::getDOMChildren($element, 'ServiceDescription', '@md');
-		foreach($elements AS $child) {
-			$language = $child->getAttributeNS('http://www.w3.org/XML/1998/namespace', 'lang');
-			if(empty($language)) $language = 'en';
-			$sp['description'][$language] = SimpleSAML_Utilities::getDOMText($child);
-		}
-		
+
+		$sp['name'] = $element->ServiceName;
+		$sp['description'] = $element->ServiceDescription;
 
 		$format = NULL;
-		$elements = SimpleSAML_Utilities::getDOMChildren($element, 'RequestedAttribute', '@md');
 		$sp['attributes'] = array();
-		foreach($elements AS $child) {
-			$attrname = $child->getAttribute('Name');
+		foreach ($element->RequestedAttribute AS $child) {
+			$attrname = $child->Name;
 			$sp['attributes'][] = $attrname;
 
-			if ($child->hasAttribute('NameFormat')) {
-				$attrformat = $child->getAttribute('NameFormat');
+			if ($child->NameFormat !== NULL) {
+				$attrformat = $child->NameFormat;
 			} else {
 				$attrformat = SAML2_Const::NAMEFORMAT_UNSPECIFIED;
 			}
@@ -1108,7 +964,6 @@ class SimpleSAML_Metadata_SAMLParser {
 			} elseif ($format !== $attrformat) {
 				$format = SAML2_Const::NAMEFORMAT_UNSPECIFIED;
 			}
-
 		}
 
 		if (empty($sp['attributes'])) {
@@ -1122,20 +977,6 @@ class SimpleSAML_Metadata_SAMLParser {
 		if ($format !== SAML2_Const::NAMEFORMAT_UNSPECIFIED && $format !== NULL) {
 			$sp['attributes.NameFormat'] = $format;
 		}
-
-	}
-
-
-	/**
-	 * This function parses NameIDFormat elements.
-	 *
-	 * @param $element The element which should be parsed.
-	 * @return URN with the supported NameIDFormat.
-	 */
-	private static function parseNameIDFormat($element) {
-		assert('$element instanceof DOMElement');
-
-		return SimpleSAML_Utilities::getDOMText($element);
 	}
 
 
@@ -1150,47 +991,24 @@ class SimpleSAML_Metadata_SAMLParser {
 	 * - 'isDefault': Whether this endpoint is the default endpoint for this type. This attribute may not exist.
 	 *
 	 * @param $element The element which should be parsed.
-	 * @param $isIndexed Wheter the endpoint is an indexed endpoint (and may have the index and isDefault attributes.).
 	 * @return Associative array with the data we have extracted from the element.
 	 */
-	private static function parseGenericEndpoint($element, $isIndexed) {
-		assert('$element instanceof DOMElement');
-		assert('is_bool($isIndexed)');
-
-		$name = $element->localName;
+	private static function parseGenericEndpoint(SAML2_XML_md_EndpointType $element) {
 
 		$ep = array();
 
-		if(!$element->hasAttribute('Binding')) {
-			throw new Exception($name . ' missing required Binding attribute.');
-		}
-		$ep['Binding'] = $element->getAttribute('Binding');
+		$ep['Binding'] = $element->Binding;
+		$ep['Location'] = $element->Location;
 
-		if(!$element->hasAttribute('Location')) {
-			throw new Exception($name . ' missing required Location attribute.');
+		if ($element->ResponseLocation !== NULL) {
+			$ep['ResponseLocation'] = $element->ResponseLocation;
 		}
-		$ep['Location'] = $element->getAttribute('Location');
 
-		if($element->hasAttribute('ResponseLocation')) {
-			$ep['ResponseLocation'] = $element->getAttribute('ResponseLocation');
-		}
+		if ($element instanceof SAML2_XML_md_IndexedEndpointType) {
+			$ep['index'] = $element->index;
 
-		if($isIndexed) {
-			if(!$element->hasAttribute('index')) {
-				throw new Exception($name . ' missing required index attribute.');
-			}
-			$ep['index'] = (int)$element->getAttribute('index');
-
-			if($element->hasAttribute('isDefault')) {
-				$t = $element->getAttribute('isDefault');
-				if($t === 'false') {
-					$ep['isDefault'] = FALSE;
-				} elseif($t === 'true') {
-					$ep['isDefault'] = TRUE;
-				} else {
-					throw new Exception('Invalid value for isDefault attribute on ' .
-						$name . ' element: ' . $t);
-				}
+			if ($element->isDefault !== NULL) {
+				$ep['isDefault'] = $element->isDefault;
 			}
 		}
 
@@ -1201,19 +1019,14 @@ class SimpleSAML_Metadata_SAMLParser {
 	/**
 	 * Extract generic endpoints.
 	 *
-	 * @param DOMElement $element  The element we should extract an endpoint list from.
-	 * @param string $name  The name of the elements.
-	 * @param bool $isIndexed  Whether the endpoints are indexed.
+	 * @param array $endpoints  The endpoints we should parse.
 	 * @return array  Array of parsed endpoints.
 	 */
-	private static function extractEndpoints(DOMElement $element, $name, $isIndexed) {
-		assert('is_bool($isIndexed)');
-		assert('is_string($name)');
+	private static function extractEndpoints(array $endpoints) {
 
 		$ret = array();
-		$endpoints = SimpleSAML_Utilities::getDOMChildren($element, $name, '@md');
 		foreach ($endpoints as $ep) {
-			$ret[] = self::parseGenericEndpoint($ep, $isIndexed);
+			$ret[] = self::parseGenericEndpoint($ep);
 		}
 
 		return $ret;
@@ -1230,52 +1043,39 @@ class SimpleSAML_Metadata_SAMLParser {
 	 * - 'type: The type of the key. 'X509Certificate' is the only key type we support.
 	 * - 'X509Certificate': The contents of the first X509Certificate element (if the type is 'X509Certificate ').
 	 *
-	 * @param $kd  The KeyDescriptor element.
+	 * @param SAML2_XML_md_KeyDescriptor $kd  The KeyDescriptor element.
 	 * @return Associative array describing the key, or NULL if this is an unsupported key.
 	 */
-	private static function parseKeyDescriptor($kd) {
-		assert('$kd instanceof DOMElement');
+	private static function parseKeyDescriptor(SAML2_XML_md_KeyDescriptor $kd) {
 
 		$r = array();
 
-		if($kd->hasAttribute('use')) {
-			$use = $kd->getAttribute('use');
-			if($use === 'encryption') {
-				$r['encryption'] = TRUE;
-				$r['signing'] = FALSE;
-			} elseif($use === 'signing') {
-				$r['encryption'] = FALSE;
-				$r['signing'] = TRUE;
-			} else {
-				throw new Exception('Invalid use-value for KeyDescriptor: ' . $use);
-			}
+		if ($kd->use === 'encryption') {
+			$r['encryption'] = TRUE;
+			$r['signing'] = FALSE;
+		} elseif($kd->use === 'signing') {
+			$r['encryption'] = FALSE;
+			$r['signing'] = TRUE;
 		} else {
 			$r['encryption'] = TRUE;
 			$r['signing'] = TRUE;
 		}
 
-		$keyInfo = SimpleSAML_Utilities::getDOMChildren($kd, 'KeyInfo', '@ds');
-		if(count($keyInfo) === 0) {
-			throw new Exception('Missing required KeyInfo field for KeyDescriptor.');
-		}
-		$keyInfo = $keyInfo[0];
+		$keyInfo = $kd->KeyInfo;
 
-		$X509Data = SimpleSAML_Utilities::getDOMChildren($keyInfo, 'X509Data', '@ds');
-		if(count($X509Data) === 0) {
-			return NULL;
-		}
-		$X509Data = $X509Data[0];
-
-		$X509Certificate = SimpleSAML_Utilities::getDOMChildren($X509Data, 'X509Certificate', '@ds');
-		if(count($X509Certificate) === 0) {
-			return NULL;
+		foreach ($keyInfo->info as $i) {
+			if ($i instanceof SAML2_XML_ds_X509Data) {
+				foreach ($i->data as $d) {
+					if ($d instanceof SAML2_XML_ds_X509Certificate) {
+						$r['type'] = 'X509Certificate';
+						$r['X509Certificate'] = $d->certificate;
+						return $r;
+					}
+				}
+			}
 		}
-		$X509Certificate = $X509Certificate[0];
-
-		$r['type'] = 'X509Certificate';
-		$r['X509Certificate'] = SimpleSAML_Utilities::getDOMText($X509Certificate);
 
-		return $r;
+		return NULL;
 	}
 
 
@@ -1349,68 +1149,7 @@ class SimpleSAML_Metadata_SAMLParser {
 			throw new Exception('Expected first element in the metadata document to be an EntityDescriptor element.');
 		}
 
-		return $ed;
-	}
-
-
-	/**
-	 * This function extracts a list of supported protocols from a SPSSODescriptor or IDPSSODescriptor element.
-	 *
-	 * @param $element The SPSSODescriptor or IDPSSODescriptor element.
-	 * @return Array with the supported protocols.
-	 */
-	private static function getSupportedProtocols($element) {
-		assert('$element instanceof DOMElement');
-
-		/* The protocolSupportEnumeration is a required attribute. */
-		if(!$element->hasAttribute('protocolSupportEnumeration')) {
-			throw new Exception($element->tagName . ' is missing the required protocolSupportEnumeration attribute.');
-		}
-
-		/* The attribute is a space seperated list of supported protocols. */
-		$supProt = $element->getAttribute('protocolSupportEnumeration');
-		$supProt = explode(' ', $supProt);
-
-		return $supProt;
-	}
-
-
-	/**
-	 * This function processes a signature element in an EntityDescriptor element.
-	 *
-	 * It will attempt to validate the EntityDescriptor element using the signature. If the signature
-	 * is good, it will and will store the fingerprint the certificate in the $validatedFingerprint variable.
-	 *
-	 * @param $element  The ds:Signature element.
-	 */
-	private function processSignature($element) {
-		assert('$element instanceof DOMElement');
-
-		/* We want to validate the EntityDescriptor which contains the signature. */
-		$entityDescriptor = $element->parentNode;
-		assert('$entityDescriptor instanceof DOMElement');
-
-		/*
-		 * Make a copy of the entity descriptor, so that the validator can
-		 * change the DOM tree in any way it wants.
-		 */
-		$doc = new DOMDocument();
-		$entityDescriptor = $doc->importNode($entityDescriptor, TRUE);
-		$doc->appendChild($entityDescriptor);
-
-		/* Attempt to check the signature. */
-		try {
-			$validator = new SimpleSAML_XML_Validator($entityDescriptor, 'ID');
-
-			if($validator->isNodeValidated($entityDescriptor)) {
-				/* The EntityDescriptor is signed. Store the validator in $this->validator, so
-				 * that it can be used to verify the fingerprint of the certificate later.
-				 */
-				$this->validator[] = $validator;
-			}
-		} catch(Exception $e) {
-			/* Ignore validation errors and pretend that this EntityDescriptor is unsigned. */
-		}
+		return new SAML2_XML_md_EntityDescriptor($ed);
 	}
 
 
@@ -1424,13 +1163,12 @@ class SimpleSAML_Metadata_SAMLParser {
 	 */
 	public function validateFingerprint($fingerprint) {
 
-		foreach($this->validator as $validator) {
-			try {
-				$validator->validateFingerprint($fingerprint);
-				return TRUE;
-			} catch(Exception $e) {
-				/* Validation with this validator failed. */
-				SimpleSAML_Logger::debug('Validation of fingerprint failed: ' . $e->getMessage());
+		foreach ($this->validators as $validator) {
+			foreach ($validator->getValidatingCertificates() as $cert) {
+				$fp = strtolower(sha1(base64_decode($cert)));
+				if ($fp === $fingerprint) {
+					return TRUE;
+				}
 			}
 		}
 
@@ -1438,5 +1176,3 @@ class SimpleSAML_Metadata_SAMLParser {
 	}
 
 }
-
-?>
\ No newline at end of file