/** * @testdox getVariables() tests * @dataProvider getGetVariablesTests */ public function testGetVariables($expr, $expected) { if ($expected instanceof Exception) { $this->setExpectedException(get_class($expected), $expected->getMessage()); } $this->assertSame($expected, XPathHelper::getVariables($expr)); }
/** * Return a list of parameters in use in given XSL * * @param string $xsl XSL source * @return array Alphabetically sorted list of unique parameter names */ public static function getParametersFromXSL($xsl) { $paramNames = []; // Wrap the XSL in boilerplate code because it might not have a root element $xsl = '<xsl:stylesheet xmlns:xsl="' . self::XMLNS_XSL . '">' . '<xsl:template>' . $xsl . '</xsl:template>' . '</xsl:stylesheet>'; $dom = new DOMDocument(); $dom->loadXML($xsl); $xpath = new DOMXPath($dom); // Start by collecting XPath expressions in XSL elements $query = '//xsl:*/@match | //xsl:*/@select | //xsl:*/@test'; foreach ($xpath->query($query) as $attribute) { foreach (XPathHelper::getVariables($attribute->value) as $varName) { // Test whether this is the name of a local variable $varQuery = 'ancestor-or-self::*/' . 'preceding-sibling::xsl:variable[@name="' . $varName . '"]'; if (!$xpath->query($varQuery, $attribute)->length) { $paramNames[] = $varName; } } } // Collecting XPath expressions in attribute value templates $query = '//*[namespace-uri() != "' . self::XMLNS_XSL . '"]' . '/@*[contains(., "{")]'; foreach ($xpath->query($query) as $attribute) { $tokens = AVTHelper::parse($attribute->value); foreach ($tokens as $token) { if ($token[0] !== 'expression') { continue; } foreach (XPathHelper::getVariables($token[1]) as $varName) { // Test whether this is the name of a local variable $varQuery = 'ancestor-or-self::*/' . 'preceding-sibling::xsl:variable[@name="' . $varName . '"]'; if (!$xpath->query($varQuery, $attribute)->length) { $paramNames[] = $varName; } } } } // Dedupe and sort names $paramNames = array_unique($paramNames); sort($paramNames); return $paramNames; }