Source of file Query.php
Size: 5,506 Bytes - Last Modified: 2014-03-12T23:21:18+01:00
/home/theseer/Downloads/ZendFramework-2.3.0/library/Zend/Dom/Document/Query.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 | <?php /** * Zend Framework (http://framework.zend.com/) * * @link http://github.com/zendframework/zf2 for the canonical source repository * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ namespace Zend\Dom\Document; use Zend\Dom\DOMXPath; use Zend\Dom\Document; /** * Query object executable in a Zend\Dom\Document */ class Query { /**#@+ * Query types */ const TYPE_XPATH = 'TYPE_XPATH'; const TYPE_CSS = 'TYPE_CSS'; /**#@-*/ /** * Perform the query on Document * * @param string $expression CSS selector or XPath query * @param Document $document Document to query * @param string $type The type of $expression * @return NodeList */ public static function execute($expression, Document $document, $type = self::TYPE_XPATH) { // Expression check if ($type === static::TYPE_CSS) { $expression = static::cssToXpath($expression); } $xpath = new DOMXPath($document->getDomDocument()); $xpathNamespaces = $document->getXpathNamespaces(); foreach ($xpathNamespaces as $prefix => $namespaceUri) { $xpath->registerNamespace($prefix, $namespaceUri); } if ($xpathPhpfunctions = $document->getXpathPhpFunctions()) { $xpath->registerNamespace('php', 'http://php.net/xpath'); ($xpathPhpfunctions === true) ? $xpath->registerPHPFunctions() : $xpath->registerPHPFunctions($xpathPhpfunctions); } $nodeList = $xpath->queryWithErrorException($expression); return new NodeList($nodeList); } /** * Transform CSS expression to XPath * * @param string $path * @return string */ public static function cssToXpath($path) { $path = (string) $path; if (strstr($path, ',')) { $paths = explode(',', $path); $expressions = array(); foreach ($paths as $path) { $xpath = static::cssToXpath(trim($path)); if (is_string($xpath)) { $expressions[] = $xpath; } elseif (is_array($xpath)) { $expressions = array_merge($expressions, $xpath); } } return implode('|', $expressions); } $paths = array('//'); $path = preg_replace('|\s+>\s+|', '>', $path); $segments = preg_split('/\s+/', $path); foreach ($segments as $key => $segment) { $pathSegment = static::_tokenize($segment); if (0 == $key) { if (0 === strpos($pathSegment, '[contains(')) { $paths[0] .= '*' . ltrim($pathSegment, '*'); } else { $paths[0] .= $pathSegment; } continue; } if (0 === strpos($pathSegment, '[contains(')) { foreach ($paths as $pathKey => $xpath) { $paths[$pathKey] .= '//*' . ltrim($pathSegment, '*'); $paths[] = $xpath . $pathSegment; } } else { foreach ($paths as $pathKey => $xpath) { $paths[$pathKey] .= '//' . $pathSegment; } } } if (1 == count($paths)) { return $paths[0]; } return implode('|', $paths); } /** * Tokenize CSS expressions to XPath * * @param string $expression * @return string */ protected static function _tokenize($expression) { // Child selectors $expression = str_replace('>', '/', $expression); // IDs $expression = preg_replace('|#([a-z][a-z0-9_-]*)|i', '[@id=\'$1\']', $expression); $expression = preg_replace('|(?<![a-z0-9_-])(\[@id=)|i', '*$1', $expression); // arbitrary attribute strict equality $expression = preg_replace_callback( '|\[@?([a-z0-9_-]+)=[\'"]([^\'"]+)[\'"]\]|i', function ($matches) { return '[@' . strtolower($matches[1]) . "='" . $matches[2] . "']"; }, $expression ); // arbitrary attribute contains full word $expression = preg_replace_callback( '|\[([a-z0-9_-]+)~=[\'"]([^\'"]+)[\'"]\]|i', function ($matches) { return "[contains(concat(' ', normalize-space(@" . strtolower($matches[1]) . "), ' '), ' " . $matches[2] . " ')]"; }, $expression ); // arbitrary attribute contains specified content $expression = preg_replace_callback( '|\[([a-z0-9_-]+)\*=[\'"]([^\'"]+)[\'"]\]|i', function ($matches) { return "[contains(@" . strtolower($matches[1]) . ", '" . $matches[2] . "')]"; }, $expression ); // Classes if(false === strpos($expression, "[@")) { $expression = preg_replace( '|\.([a-z][a-z0-9_-]*)|i', "[contains(concat(' ', normalize-space(@class), ' '), ' \$1 ')]", $expression ); } /** ZF-9764 -- remove double asterisk */ $expression = str_replace('**', '*', $expression); return $expression; } } |