*/ class ImsManifestMetadataExtractor implements MetadataExtractor { /** * @see MetadataExtractor::extract() */ public function extract($manifest) { if ($manifest instanceof DOMDocument) { $bases = []; // get the base for paths. $xpath = new DOMXPath($manifest); foreach ($xpath->query('namespace::*', $manifest->ownerDocument) as $node) { $bases[str_replace('xmlns:', '', $node->nodeName)] = $node->nodeValue; } $manifestElt = $manifest->documentElement; $rootNs = $manifestElt->namespaceURI; // Extract metadata on a . $xpath->registerNamespace('man', $rootNs); // Prepare data structure to be returned. $metadata = []; $resourcesElt = $xpath->query('/man:manifest/man:resources/man:resource'); foreach ($resourcesElt as $resourceElt) { $identifier = $resourceElt->getAttribute('identifier'); $href = $resourceElt->getAttribute('href'); $type = $resourceElt->getAttribute('type'); $metadataElts = $xpath->query('man:metadata', $resourceElt); foreach ($metadataElts as $metadataElt) { // Ask for metadata domains. $domainElts = $xpath->query('*[not(self::man:schema) and not(self::man:schemaversion)]', $metadataElt); foreach ($domainElts as $domainElt) { $trail = []; $visited = []; $path = []; $parent = null; array_push($trail, $domainElt); while (count($trail) > 0) { $currentElt = array_pop($trail); if (!$currentElt instanceof DOMText && in_array($currentElt, $visited, true) === false) { // Hierarchical node, 1st visit. // Push current for a future ascending exploration. array_push($trail, $currentElt); // Push children on the trail for descending exploration. $nodesToExplore = $currentElt->childNodes; if ($nodesToExplore) { for ($i = ($nodesToExplore->length - 1); $i >= 0; $i--) { array_push($trail, $nodesToExplore->item($i)); } } // Set current as visited. array_push($visited, $currentElt); // Update the path. array_push($path, $currentElt->namespaceURI . '#' . $currentElt->localName); // Reference parent for leaf nodes. $parent = $currentElt; } elseif ($currentElt instanceof DOMText && ctype_space($currentElt->wholeText) === false) { // Leaf node, 1st and only visit. $metadataValue = new ImsManifestMetadataValue($identifier, $type, $href, $path, $currentElt->wholeText); if ($parent !== null && $parent->hasAttributeNS($bases['xml'], 'lang')) { $metadataValue->setLanguage($parent->getAttributeNS($bases['xml'], 'lang')); } if (isset($metadata[$identifier]) === false) { $metadata[$identifier] = []; } $metadata[$identifier][] = $metadataValue; } elseif (in_array($currentElt, $visited, true) === true) { // Hierarchical node, second visit (ascending). // Update the path. array_pop($path); } } } } } return $metadata; } else { throw new MetadataExtractionException(__('The manifest argument must be an instance of DOMDocument.')); } } }