/common/libraries/plugin/pear/phing/filters/XsltFilter.php
PHP | 453 lines | 209 code | 55 blank | 189 comment | 14 complexity | c6f7649fb8e837a318c20480a4d7a5eb MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, LGPL-2.1, LGPL-3.0, GPL-3.0, MIT
- <?php
-
- /*
- * $Id: XsltFilter.php 557 2009-08-29 13:54:38Z mrook $
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * This software consists of voluntary contributions made by many individuals
- * and is licensed under the LGPL. For more information please see
- * <http://phing.info>.
- */
-
- include_once 'phing/filters/BaseParamFilterReader.php';
- include_once 'phing/filters/ChainableReader.php';
-
- /**
- * Applies XSL stylesheet to incoming text.
- *
- * Uses PHP XSLT support (libxslt).
- *
- * @author Hans Lellelid <hans@velum.net>
- * @author Yannick Lecaillez <yl@seasonfive.com>
- * @author Andreas Aderhold <andi@binarycloud.com>
- * @version $Id: XsltFilter.php 557 2009-08-29 13:54:38Z mrook $
- * @see FilterReader
- * @package phing.filters
- */
- class XsltFilter extends BaseParamFilterReader implements ChainableReader
- {
-
- /**
- * Path to XSL stylesheet.
- * @var string
- */
- private $xslFile = null;
-
- /**
- * Whether XML file has been transformed.
- * @var boolean
- */
- private $processed = false;
-
- /**
- * XSLT Params.
- * @var array
- */
- private $xsltParams = array();
-
- /**
- * Whether to use loadHTML() to parse the input XML file.
- */
- private $html = false;
-
- /**
- * Whether to resolve entities in the XML document (see
- * {@link http://www.php.net/manual/en/class.domdocument.php#domdocument.props.resolveexternals}
- * for more details).
- *
- * @var bool
- *
- * @since 2.4
- */
- private $resolveDocumentExternals = false;
-
- /**
- * Whether to resolve entities in the stylesheet.
- *
- * @var bool
- *
- * @since 2.4
- */
- private $resolveStylesheetExternals = false;
-
- /**
- * Create new XSLT Param object, to handle the <param/> nested element.
- * @return XSLTParam
- */
- function createParam()
- {
- $num = array_push($this->xsltParams, new XSLTParam());
- return $this->xsltParams[$num - 1];
- }
-
- /**
- * Sets the XSLT params for this class.
- * This is used to "clone" this class, in the chain() method.
- * @param array $params
- */
- function setParams($params)
- {
- $this->xsltParams = $params;
- }
-
- /**
- * Returns the XSLT params set for this class.
- * This is used to "clone" this class, in the chain() method.
- * @return array
- */
- function getParams()
- {
- return $this->xsltParams;
- }
-
- /**
- * Set the XSLT stylesheet.
- * @param mixed $file PhingFile object or path.
- */
- function setStyle(PhingFile $file)
- {
- $this->xslFile = $file;
- }
-
- /**
- * Whether to use HTML parser for the XML.
- * This is supported in libxml2 -- Yay!
- * @return boolean
- */
- function getHtml()
- {
- return $this->html;
- }
-
- /**
- * Whether to use HTML parser for XML.
- * @param boolean $b
- */
- function setHtml($b)
- {
- $this->html = (boolean) $b;
- }
-
- /**
- * Get the path to XSLT stylesheet.
- * @return mixed XSLT stylesheet path.
- */
- function getStyle()
- {
- return $this->xslFile;
- }
-
- /**
- * Whether to resolve entities in document.
- *
- * @param bool $resolveExternals
- *
- * @since 2.4
- */
- function setResolveDocumentExternals($resolveExternals)
- {
- $this->resolveDocumentExternals = (bool) $resolveExternals;
- }
-
- /**
- * @return bool
- *
- * @since 2.4
- */
- function getResolveDocumentExternals()
- {
- return $this->resolveDocumentExternals;
- }
-
- /**
- * Whether to resolve entities in stylesheet.
- *
- * @param bool $resolveExternals
- *
- * @since 2.4
- */
- function setResolveStylesheetExternals($resolveExternals)
- {
- $this->resolveStylesheetExternals = (bool) $resolveExternals;
- }
-
- /**
- * @return bool
- *
- * @since 2.4
- */
- function getResolveStylesheetExternals()
- {
- return $this->resolveStylesheetExternals;
- }
-
- /**
- * Reads stream, applies XSLT and returns resulting stream.
- * @return string transformed buffer.
- * @throws BuildException - if XSLT support missing, if error in xslt processing
- */
- function read($len = null)
- {
-
- if (! class_exists('XSLTProcessor'))
- {
- throw new BuildException("Could not find the XSLTProcessor class. Make sure PHP has been compiled/configured to support XSLT.");
- }
-
- if ($this->processed === true)
- {
- return - 1; // EOF
- }
-
- if (! $this->getInitialized())
- {
- $this->_initialize();
- $this->setInitialized(true);
- }
-
- // Read XML
- $_xml = null;
- while (($data = $this->in->read($len)) !== - 1)
- $_xml .= $data;
-
- if ($_xml === null)
- { // EOF?
- return - 1;
- }
-
- if (empty($_xml))
- {
- $this->log("XML file is empty!", Project :: MSG_WARN);
- return ''; // return empty string, don't attempt to apply XSLT
- }
-
- // Read XSLT
- $_xsl = null;
- $xslFr = new FileReader($this->xslFile);
- $xslFr->readInto($_xsl);
-
- $this->log("Tranforming XML " . $this->in->getResource() . " using style " . $this->xslFile->getPath(), Project :: MSG_VERBOSE);
-
- $out = '';
- try
- {
- $out = $this->process($_xml, $_xsl);
- $this->processed = true;
- }
- catch (IOException $e)
- {
- throw new BuildException($e);
- }
-
- return $out;
- }
-
- // {{{ method _ProcessXsltTransformation($xml, $xslt) throws BuildException
- /**
- * Try to process the XSLT transformation
- *
- * @param string XML to process.
- * @param string XSLT sheet to use for the processing.
- *
- * @throws BuildException On XSLT errors
- */
- protected function process($xml, $xsl)
- {
-
- $processor = new XSLTProcessor();
-
- // Create and setup document.
- $xmlDom = new DOMDocument();
- $xmlDom->resolveExternals = $this->resolveDocumentExternals;
-
- // Create and setup stylesheet.
- $xslDom = new DOMDocument();
- $xslDom->resolveExternals = $this->resolveStylesheetExternals;
-
- if ($this->html)
- {
- $xmlDom->loadHTML($xml);
- }
- else
- {
- $xmlDom->loadXML($xml);
- }
-
- $xslDom->loadxml($xsl);
-
- $processor->importStylesheet($xslDom);
-
- // ignoring param "type" attrib, because
- // we're only supporting direct XSL params right now
- foreach ($this->xsltParams as $param)
- {
- $this->log("Setting XSLT param: " . $param->getName() . "=>" . $param->getExpression(), Project :: MSG_DEBUG);
- $processor->setParameter(null, $param->getName(), $param->getExpression());
- }
-
- $errorlevel = error_reporting();
- error_reporting($errorlevel & ~ E_WARNING);
- @$result = $processor->transformToXML($xmlDom);
- error_reporting($errorlevel);
-
- if (false === $result)
- {
- //$errno = xslt_errno($processor);
- //$err = xslt_error($processor);
- throw new BuildException("XSLT Error");
- }
- else
- {
- return $result;
- }
- }
-
- /**
- * Creates a new XsltFilter using the passed in
- * Reader for instantiation.
- *
- * @param Reader A Reader object providing the underlying stream.
- * Must not be <code>null</code>.
- *
- * @return Reader A new filter based on this configuration, but filtering
- * the specified reader
- */
- function chain(Reader $reader)
- {
- $newFilter = new XsltFilter($reader);
- $newFilter->setProject($this->getProject());
- $newFilter->setStyle($this->getStyle());
- $newFilter->setInitialized(true);
- $newFilter->setParams($this->getParams());
- $newFilter->setHtml($this->getHtml());
- return $newFilter;
- }
-
- /**
- * Parses the parameters to get stylesheet path.
- */
- private function _initialize()
- {
- $params = $this->getParameters();
- if ($params !== null)
- {
- for($i = 0, $_i = count($params); $i < $_i; $i ++)
- {
- if ($params[$i]->getType() === null)
- {
- if ($params[$i]->getName() === "style")
- {
- $this->setStyle($params[$i]->getValue());
- }
- }
- elseif ($params[$i]->getType() == "param")
- {
- $xp = new XSLTParam();
- $xp->setName($params[$i]->getName());
- $xp->setExpression($params[$i]->getValue());
- $this->xsltParams[] = $xp;
- }
- }
- }
- }
-
- }
-
- /**
- * Class that holds an XSLT parameter.
- *
- * @package phing.filters
- */
- class XSLTParam
- {
-
- private $name;
-
- private $expr;
-
- /**
- * Sets param name.
- * @param string $name
- */
- public function setName($name)
- {
- $this->name = $name;
- }
-
- /**
- * Get param name.
- * @return string
- */
- public function getName()
- {
- return $this->name;
- }
-
- /**
- * Sets expression value (alias to the setExpression()) method.
- *
- * @param string $v
- * @see setExpression()
- */
- public function setValue($v)
- {
- $this->setExpression($v);
- }
-
- /**
- * Gets expression value (alias to the getExpression()) method.
- *
- * @param string $v
- * @see getExpression()
- */
- public function getValue()
- {
- return $this->getExpression();
- }
-
- /**
- * Sets expression value.
- * @param string $expr
- */
- public function setExpression($expr)
- {
- $this->expr = $expr;
- }
-
- /**
- * Sets expression to dynamic register slot.
- * @param RegisterSlot $expr
- */
- public function setListeningExpression(RegisterSlot $expr)
- {
- $this->expr = $expr;
- }
-
- /**
- * Returns expression value -- performs lookup if expr is registerslot.
- * @return string
- */
- public function getExpression()
- {
- if ($this->expr instanceof RegisterSlot)
- {
- return $this->expr->getValue();
- }
- else
- {
- return $this->expr;
- }
- }
- }