/tine20/library/Zend/Dom/Query/Css2Xpath.php

https://gitlab.com/rsilveira1987/Expresso · PHP · 141 lines · 86 code · 10 blank · 45 comment · 13 complexity · 92522ad5fc0baaab04afc13cd8ebe623 MD5 · raw file

  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Dom
  17. * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
  18. * @license http://framework.zend.com/license/new-bsd New BSD License
  19. */
  20. /**
  21. * Transform CSS selectors to XPath
  22. *
  23. * @package Zend_Dom
  24. * @subpackage Query
  25. * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
  26. * @license http://framework.zend.com/license/new-bsd New BSD License
  27. * @version $Id: Css2Xpath.php 10020 2009-08-18 14:34:09Z j.fischer@metaways.de $
  28. */
  29. class Zend_Dom_Query_Css2Xpath
  30. {
  31. /**
  32. * Transform CSS expression to XPath
  33. *
  34. * @param string $path
  35. * @return string|array
  36. */
  37. public static function transform($path)
  38. {
  39. $path = (string) $path;
  40. if (strstr($path, ',')) {
  41. $paths = explode(',', $path);
  42. $expressions = array();
  43. foreach ($paths as $path) {
  44. $xpath = self::transform(trim($path));
  45. if (is_string($xpath)) {
  46. $expressions[] = $xpath;
  47. } elseif (is_array($xpath)) {
  48. $expressions = array_merge($expressions, $xpath);
  49. }
  50. }
  51. return $expressions;
  52. }
  53. $paths = array('//');
  54. $segments = preg_split('/\s+/', $path);
  55. foreach ($segments as $key => $segment) {
  56. $pathSegment = self::_tokenize($segment);
  57. if (0 == $key) {
  58. if (0 === strpos($pathSegment, '[contains(@class')) {
  59. $paths[0] .= '*' . $pathSegment;
  60. } else {
  61. $paths[0] .= $pathSegment;
  62. }
  63. continue;
  64. }
  65. if (0 === strpos($pathSegment, '[contains(@class')) {
  66. foreach ($paths as $key => $xpath) {
  67. $paths[$key] .= '//*' . $pathSegment;
  68. $paths[] = $xpath . $pathSegment;
  69. }
  70. } else {
  71. foreach ($paths as $key => $xpath) {
  72. $paths[$key] .= '//' . $pathSegment;
  73. }
  74. }
  75. }
  76. if (1 == count($paths)) {
  77. return $paths[0];
  78. }
  79. return implode(' | ', $paths);
  80. }
  81. /**
  82. * Tokenize CSS expressions to XPath
  83. *
  84. * @param string $expression
  85. * @return string
  86. */
  87. protected static function _tokenize($expression)
  88. {
  89. // Child selectors
  90. $expression = str_replace('>', '/', $expression);
  91. // IDs
  92. $expression = preg_replace('|#([a-z][a-z0-9_-]*)|i', '[@id=\'$1\']', $expression);
  93. $expression = preg_replace('|(?<![a-z0-9_-])(\[@id=)|i', '*$1', $expression);
  94. // arbitrary attribute strict equality
  95. if (preg_match('|([a-z]+)\[([a-z0-9_-]+)=[\'"]([^\'"]+)[\'"]\]|i', $expression)) {
  96. $expression = preg_replace_callback(
  97. '|([a-z]+)\[([a-z0-9_-]+)=[\'"]([^\'"]+)[\'"]\]|i',
  98. create_function(
  99. '$matches',
  100. 'return $matches[1] . "[@" . strtolower($matches[2]) . "=\'" . $matches[3] . "\']";'
  101. ),
  102. $expression
  103. );
  104. }
  105. // arbitrary attribute contains full word
  106. if (preg_match('|([a-z]+)\[([a-z0-9_-]+)~=[\'"]([^\'"]+)[\'"]\]|i', $expression)) {
  107. $expression = preg_replace_callback(
  108. '|([a-z]+)\[([a-z0-9_-]+)~=[\'"]([^\'"]+)[\'"]\]|i',
  109. create_function(
  110. '$matches',
  111. 'return $matches[1] . "[contains(@" . strtolower($matches[2]) . ", \' $matches[3] \')]";'
  112. ),
  113. $expression
  114. );
  115. }
  116. // arbitrary attribute contains specified content
  117. if (preg_match('|([a-z]+)\[([a-z0-9_-]+)\*=[\'"]([^\'"]+)[\'"]\]|i', $expression)) {
  118. $expression = preg_replace_callback(
  119. '|([a-z]+)\[([a-z0-9_-]+)\*=[\'"]([^\'"]+)[\'"]\]|i',
  120. create_function(
  121. '$matches',
  122. 'return $matches[1] . "[contains(@" . strtolower($matches[2]) . ", \'" . $matches[3] . "\')]";'
  123. ),
  124. $expression
  125. );
  126. }
  127. // Classes
  128. $expression = preg_replace('|\.([a-z][a-z0-9_-]*)|i', "[contains(@class, ' \$1 ')]", $expression);
  129. return $expression;
  130. }
  131. }