/** * Validates the node against a given Schematron validation file. * * @param DOMDocument The validator to use. * * @return AgaviXmlConfigDomDocument The transformed validation document. * * @author Noah Fontes <*****@*****.**> * @since 1.0.0 */ public function transform(DOMDocument $schema) { // do we even have a document? if ($this->node === null) { throw new AgaviParseException('Schema validation failed because no document could be parsed'); } // is it an ISO Schematron file? if (!$schema->documentElement || $schema->documentElement->namespaceURI != self::NAMESPACE_SCHEMATRON_ISO) { throw new AgaviParseException(sprintf('Schema file "%s" is invalid', $schema->documentURI)); } // transform the .sch file to a validation stylesheet using the Schematron implementation $validatorImpl = $schema; $first = true; foreach ($this->getProcessors() as $processor) { if ($first) { // set some vars for the schema $this->prepareProcessor($processor); } try { $validatorImpl = $processor->transformToDoc($validatorImpl); } catch (Exception $e) { if ($first) { $this->cleanupProcessor($processor); } throw new AgaviParseException(sprintf('Could not transform schema file "%s": %s', $schema->documentURI, $e->getMessage()), 0, $e); } if ($first) { $this->cleanupProcessor($processor); $first = false; } } // it transformed fine. but did we get a proper stylesheet instance at all? wrong namespaces can lead to empty docs that only have an XML prolog if (!$validatorImpl->documentElement || $validatorImpl->documentElement->namespaceURI != self::NAMESPACE_XSL_1999) { throw new AgaviParseException(sprintf('Processing using schema file "%s" resulted in an invalid stylesheet', $schema->documentURI)); } // all fine so far. let us import the stylesheet try { $validator = new AgaviXsltProcessor(); $validator->importStylesheet($validatorImpl); } catch (Exception $e) { throw new AgaviParseException(sprintf('Could not process the schema file "%s": %s', $schema->documentURI, $e->getMessage()), 0, $e); } // run the validation by transforming our document using the generated validation stylesheet try { $result = $validator->transformToDoc($this->node); } catch (Exception $e) { throw new AgaviParseException(sprintf('Could not validate the document against the schema file "%s": %s', $schema->documentURI, $e->getMessage()), 0, $e); } return $result; }
/** * Transform the document using info from embedded processing instructions * and given stylesheets. * * @param AgaviXmlConfigDomDocument The document to act upon. * @param string The environment name. * @param string The context name. * @param array An array of transformation information. * @param array An array of XSL stylesheets in DOMDocument instances. * * @return AgaviXmlConfigDomDocument The transformed document. * * @author David Zülke <*****@*****.**> * @author Noah Fontes <*****@*****.**> * @since 0.11.0 */ public static function transform(AgaviXmlConfigDomDocument $document, $environment, $context, array $transformationInfo = array(), $transformations = array()) { // loop over all the paths we found and load the files foreach ($transformationInfo as $href) { try { $xsl = new AgaviXmlConfigDomDocument(); $xsl->load($href); } catch (DOMException $dome) { throw new AgaviParseException(sprintf('Configuration file "%s" could not be parsed: Could not load XSL stylesheet "%s": %s', $document->documentURI, $href, $dome->getMessage()), 0, $dome); } // add them to the list of transformations to be done $transformations[] = $xsl; } // now let's perform the transformations foreach ($transformations as $xsl) { // load the stylesheet document into an XSLTProcessor instance try { $proc = new AgaviXsltProcessor(); $proc->registerPHPFunctions(); $proc->importStylesheet($xsl); } catch (Exception $e) { throw new AgaviParseException(sprintf('Configuration file "%s" could not be parsed: Could not import XSL stylesheet "%s": %s', $document->documentURI, $xsl->documentURI, $e->getMessage()), 0, $e); } // set some info (config file path, context name, environment name) as params // first arg is the namespace URI, which PHP doesn't support. awesome. see http://bugs.php.net/bug.php?id=30622 for the sad details // we could use "agavi:context" etc, that does work even without such a prefix being declared in the stylesheet, but that would be completely non-XML-ish, confusing, and against the spec. so we use dots instead. // the string casts are required for hhvm ($context could be null for example and hhvm bails out on that) $proc->setParameter('', array('agavi.config_path' => (string) $document->documentURI, 'agavi.environment' => (string) $environment, 'agavi.context' => (string) $context)); try { // transform the doc $newdoc = $proc->transformToDoc($document); } catch (Exception $e) { throw new AgaviParseException(sprintf('Configuration file "%s" could not be parsed: Could not transform the document using the XSL stylesheet "%s": %s', $document->documentURI, $xsl->documentURI, $e->getMessage()), 0, $e); } // no errors and we got a document back? excellent. this will be our new baby from now. time to kill the old one // get the old document URI $documentUri = $document->documentURI; // and assign the new document to the old one $document = $newdoc; // save the old document URI just in case $document->documentURI = $documentUri; } return $document; }