* * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Behat\Mink\Selector\Xpath; /** * XPath manipulation utility. * * @author Graham Bates * @author Christophe Coevoet */ class Manipulator { /** * Regex to find union operators not inside brackets. */ const UNION_PATTERN = '/\|(?![^\[]*\])/'; /** * Prepends the XPath prefix to the given XPath. * * The returned XPath will match elements matching the XPath inside an element * matching the prefix. * * @param string $xpath * @param string $prefix * * @return string */ public function prepend($xpath, $prefix) { $expressions = array(); // If the xpath prefix contains a union we need to wrap it in parentheses. if (preg_match(self::UNION_PATTERN, $prefix)) { $prefix = '('.$prefix.')'; } // Split any unions into individual expressions. foreach (preg_split(self::UNION_PATTERN, $xpath) as $expression) { $expression = trim($expression); $parenthesis = ''; // If the union is inside some braces, we need to preserve the opening braces and apply // the prefix only inside it. if (preg_match('/^[\(\s*]+/', $expression, $matches)) { $parenthesis = $matches[0]; $expression = substr($expression, strlen($parenthesis)); } // add prefix before element selector if (0 === strpos($expression, '/')) { $expression = $prefix.$expression; } else { $expression = $prefix.'/'.$expression; } $expressions[] = $parenthesis.$expression; } return implode(' | ', $expressions); } }