/** * 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 != AgaviXmlConfigParser::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 try { $initialProcessor = self::$processors[0]; $initialProcessor->setParameter('', $this->getParameters()); // ...and do the actual transformations $validatorImpl = $initialProcessor->transformToDoc($schema); for ($i = 1; $i < self::$processorCount; $i++) { $validatorImpl = self::$processors[$i]->transformToDoc($validatorImpl); } // for some reason we can't clone XSLTProcessor instances, so we have to // go back and remove all the parameters :( foreach (array_keys($this->getParameters()) as $parameter) { $initialProcessor->removeParameter('', $parameter); } } catch (Exception $e) { throw new AgaviParseException(sprintf('Could not transform schema file "%s": %s', $schema->documentURI, $e->getMessage())); } // 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 != AgaviXmlConfigParser::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 AgaviXmlConfigXsltProcessor(); $validator->importStylesheet($validatorImpl); } catch (Exception $e) { throw new AgaviParseException(sprintf('Could not process the schema file "%s": %s', $schema->documentURI, $e->getMessage())); } // 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())); } 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())); } // 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 AgaviXmlConfigXsltProcessor(); $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())); } // 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. $proc->setParameter('', array('agavi.config_path' => $document->documentURI, 'agavi.environment' => $environment, 'agavi.context' => $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())); } // 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; }