/** * Transforms a given document according to xml-stylesheet processing * instructions * * @param AgaviXmlConfigDomDocument The document to act upon. * @param string The environment name. * @param string The context name. * * @return AgaviXmlConfigDomDocument The transformed document. * * @author David Zülke <*****@*****.**> * @author Noah Fontes <*****@*****.**> * @since 1.0.0 */ public static function transformProcessingInstructions(AgaviXmlConfigDomDocument $document, $environment, $context) { $transformations = array(); $transformationInfo = array(); $xpath = $document->getXpath(); // see if there are <?xml-stylesheet... processing instructions $stylesheetProcessingInstructions = $xpath->query("//processing-instruction('xml-stylesheet')", $document); foreach ($stylesheetProcessingInstructions as $pi) { // yes! alright. trick: we create a doc fragment with the contents so we don't have to parse things by hand... $fragment = $document->createDocumentFragment(); $fragment->appendXml('<foo ' . $pi->data . ' />'); $type = $fragment->firstChild->getAttribute('type'); // we process only the types below... if (in_array($type, array('text/xml', 'text/xsl', 'application/xml', 'application/xsl+xml'))) { $href = $href = $fragment->firstChild->getAttribute('href'); if (strpos($href, '#') === 0) { // the href points to an embedded XSL stylesheet (with ID reference), so let's see if we can find it $stylesheets = $xpath->query("//*[@id='" . substr($href, 1) . "']", $document); if ($stylesheets->length) { // excellent. make a new doc from that element! try { $xsl = new AgaviXmlConfigDomDocument(); $xsl->appendChild($xsl->importNode($stylesheets->item(0), true)); } 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())); } // and append to the list of XSLs to process // TODO: spec mandates that external XSLs be processed first! $transformations[] = $xsl; } else { throw new AgaviParseException(sprintf('Configuration file "%s" could not be parsed because the inline stylesheet "%s" referenced in the "xml-stylesheet" processing instruction could not be found in the document.', $document->documentURI, $href)); } } else { // href references an xsl file, remember the path $transformationInfo[] = AgaviToolkit::expandDirectives($href); } // remove the processing instructions after we dealt with them $pi->parentNode->removeChild($pi); } } return self::transform($document, $environment, $context, $transformationInfo, $transformations); }