123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254 |
- <?php
- /*
- * This file is part of the Symfony package.
- *
- * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
- namespace Symfony\Component\CssSelector;
- /**
- * XPathExpr represents an XPath expression.
- *
- * This component is a port of the Python lxml library,
- * which is copyright Infrae and distributed under the BSD license.
- *
- * @author Fabien Potencier <fabien.potencier@symfony-project.com>
- */
- class XPathExpr
- {
- protected $prefix;
- protected $path;
- protected $element;
- protected $condition;
- protected $starPrefix;
- /**
- * Constructor.
- *
- * @param string $prefix Prefix for the XPath expression.
- * @param string $path Actual path of the expression.
- * @param string $element The element in the expression.
- * @param string $condition A condition for the expression.
- * @param Boolean $starPrefix Indicates whether to use a star prefix.
- */
- public function __construct($prefix = null, $path = null, $element = '*', $condition = null, $starPrefix = false)
- {
- $this->prefix = $prefix;
- $this->path = $path;
- $this->element = $element;
- $this->condition = $condition;
- $this->starPrefix = $starPrefix;
- }
- /**
- * Gets the prefix of this XPath expression.
- *
- * @return string
- */
- public function getPrefix()
- {
- return $this->prefix;
- }
- /**
- * Gets the path of this XPath expression.
- *
- * @return string
- */
- public function getPath()
- {
- return $this->path;
- }
- /**
- * Answers whether this XPath expression has a star prefix.
- *
- * @return Boolean
- */
- public function hasStarPrefix()
- {
- return $this->starPrefix;
- }
- /**
- * Gets the element of this XPath expression.
- *
- * @return string
- */
- public function getElement()
- {
- return $this->element;
- }
- /**
- * Gets the condition of this XPath expression.
- *
- * @return string
- */
- public function getCondition()
- {
- return $this->condition;
- }
- /**
- * Gets a string representation for this XPath expression.
- *
- * @return string
- */
- public function __toString()
- {
- $path = '';
- if (null !== $this->prefix) {
- $path .= $this->prefix;
- }
- if (null !== $this->path) {
- $path .= $this->path;
- }
- $path .= $this->element;
- if ($this->condition) {
- $path .= sprintf('[%s]', $this->condition);
- }
- return $path;
- }
- /**
- * Adds a condition to this XPath expression.
- * Any pre-existent condition will be ANDed to it.
- *
- * @param string $condition The condition to add.
- */
- public function addCondition($condition)
- {
- if ($this->condition) {
- $this->condition = sprintf('%s and (%s)', $this->condition, $condition);
- } else {
- $this->condition = $condition;
- }
- }
- /**
- * Adds a prefix to this XPath expression.
- * It will be prepended to any pre-existent prefixes.
- *
- * @param string $prefix The prefix to add.
- */
- public function addPrefix($prefix)
- {
- if ($this->prefix) {
- $this->prefix = $prefix.$this->prefix;
- } else {
- $this->prefix = $prefix;
- }
- }
- /**
- * Adds a condition to this XPath expression using the name of the element
- * as the desired value.
- * This method resets the element to '*'.
- */
- public function addNameTest()
- {
- if ($this->element == '*') {
- // We weren't doing a test anyway
- return;
- }
- $this->addCondition(sprintf('name() = %s', XPathExpr::xpathLiteral($this->element)));
- $this->element = '*';
- }
- /**
- * Adds a star prefix to this XPath expression.
- * This method will prepend a '*' to the path and set the star prefix flag
- * to true.
- */
- public function addStarPrefix()
- {
- /*
- Adds a /* prefix if there is no prefix. This is when you need
- to keep context's constrained to a single parent.
- */
- if ($this->path) {
- $this->path .= '*/';
- } else {
- $this->path = '*/';
- }
- $this->starPrefix = true;
- }
- /**
- * Joins this XPath expression with $other (another XPath expression) using
- * $combiner to join them.
- *
- * @param string $combiner The combiner string.
- * @param XPathExpr $other The other XPath expression to combine with
- * this one.
- */
- public function join($combiner, $other)
- {
- $prefix = (string) $this;
- $prefix .= $combiner;
- $path = $other->getPrefix().$other->getPath();
- /* We don't need a star prefix if we are joining to this other
- prefix; so we'll get rid of it */
- if ($other->hasStarPrefix() && '*/' == $path) {
- $path = '';
- }
- $this->prefix = $prefix;
- $this->path = $path;
- $this->element = $other->getElement();
- $this->condition = $other->GetCondition();
- }
- /**
- * Gets an XPath literal for $s.
- *
- * @param mixed $s Can either be a Node\ElementNode or a string.
- *
- * @return string
- */
- static public function xpathLiteral($s)
- {
- if ($s instanceof Node\ElementNode) {
- // This is probably a symbol that looks like an expression...
- $s = $s->formatElement();
- } else {
- $s = (string) $s;
- }
- if (false === strpos($s, "'")) {
- return sprintf("'%s'", $s);
- }
- if (false === strpos($s, '"')) {
- return sprintf('"%s"', $s);
- }
- $string = $s;
- $parts = array();
- while (true) {
- if (false !== $pos = strpos($string, "'")) {
- $parts[] = sprintf("'%s'", substr($string, 0, $pos));
- $parts[] = "\"'\"";
- $string = substr($string, $pos + 1);
- } else {
- $parts[] = "'$string'";
- break;
- }
- }
- return sprintf('concat(%s)', implode($parts, ', '));
- }
- }
|