* * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath\Extension; use Symfony\Component\CssSelector\Node; use Symfony\Component\CssSelector\XPath\Translator; use Symfony\Component\CssSelector\XPath\XPathExpr; /** * XPath expression translator node extension. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon * * @internal */ class NodeExtension extends AbstractExtension { const ELEMENT_NAME_IN_LOWER_CASE = 1; const ATTRIBUTE_NAME_IN_LOWER_CASE = 2; const ATTRIBUTE_VALUE_IN_LOWER_CASE = 4; private $flags; /** * @param int $flags */ public function __construct($flags = 0) { $this->flags = $flags; } /** * @param int $flag * @param bool $on * * @return $this */ public function setFlag($flag, $on) { if ($on && !$this->hasFlag($flag)) { $this->flags += $flag; } if (!$on && $this->hasFlag($flag)) { $this->flags -= $flag; } return $this; } /** * @param int $flag * * @return bool */ public function hasFlag($flag) { return (bool) ($this->flags & $flag); } /** * {@inheritdoc} */ public function getNodeTranslators() { return array( 'Selector' => array($this, 'translateSelector'), 'CombinedSelector' => array($this, 'translateCombinedSelector'), 'Negation' => array($this, 'translateNegation'), 'Function' => array($this, 'translateFunction'), 'Pseudo' => array($this, 'translatePseudo'), 'Attribute' => array($this, 'translateAttribute'), 'Class' => array($this, 'translateClass'), 'Hash' => array($this, 'translateHash'), 'Element' => array($this, 'translateElement'), ); } /** * @return XPathExpr */ public function translateSelector(Node\SelectorNode $node, Translator $translator) { return $translator->nodeToXPath($node->getTree()); } /** * @return XPathExpr */ public function translateCombinedSelector(Node\CombinedSelectorNode $node, Translator $translator) { return $translator->addCombination($node->getCombinator(), $node->getSelector(), $node->getSubSelector()); } /** * @return XPathExpr */ public function translateNegation(Node\NegationNode $node, Translator $translator) { $xpath = $translator->nodeToXPath($node->getSelector()); $subXpath = $translator->nodeToXPath($node->getSubSelector()); $subXpath->addNameTest(); if ($subXpath->getCondition()) { return $xpath->addCondition(sprintf('not(%s)', $subXpath->getCondition())); } return $xpath->addCondition('0'); } /** * @return XPathExpr */ public function translateFunction(Node\FunctionNode $node, Translator $translator) { $xpath = $translator->nodeToXPath($node->getSelector()); return $translator->addFunction($xpath, $node); } /** * @return XPathExpr */ public function translatePseudo(Node\PseudoNode $node, Translator $translator) { $xpath = $translator->nodeToXPath($node->getSelector()); return $translator->addPseudoClass($xpath, $node->getIdentifier()); } /** * @return XPathExpr */ public function translateAttribute(Node\AttributeNode $node, Translator $translator) { $name = $node->getAttribute(); $safe = $this->isSafeName($name); if ($this->hasFlag(self::ATTRIBUTE_NAME_IN_LOWER_CASE)) { $name = strtolower($name); } if ($node->getNamespace()) { $name = sprintf('%s:%s', $node->getNamespace(), $name); $safe = $safe && $this->isSafeName($node->getNamespace()); } $attribute = $safe ? '@'.$name : sprintf('attribute::*[name() = %s]', Translator::getXpathLiteral($name)); $value = $node->getValue(); $xpath = $translator->nodeToXPath($node->getSelector()); if ($this->hasFlag(self::ATTRIBUTE_VALUE_IN_LOWER_CASE)) { $value = strtolower($value); } return $translator->addAttributeMatching($xpath, $node->getOperator(), $attribute, $value); } /** * @return XPathExpr */ public function translateClass(Node\ClassNode $node, Translator $translator) { $xpath = $translator->nodeToXPath($node->getSelector()); return $translator->addAttributeMatching($xpath, '~=', '@class', $node->getName()); } /** * @return XPathExpr */ public function translateHash(Node\HashNode $node, Translator $translator) { $xpath = $translator->nodeToXPath($node->getSelector()); return $translator->addAttributeMatching($xpath, '=', '@id', $node->getId()); } /** * @return XPathExpr */ public function translateElement(Node\ElementNode $node) { $element = $node->getElement(); if ($this->hasFlag(self::ELEMENT_NAME_IN_LOWER_CASE)) { $element = strtolower($element); } if ($element) { $safe = $this->isSafeName($element); } else { $element = '*'; $safe = true; } if ($node->getNamespace()) { $element = sprintf('%s:%s', $node->getNamespace(), $element); $safe = $safe && $this->isSafeName($node->getNamespace()); } $xpath = new XPathExpr('', $element); if (!$safe) { $xpath->addNameTest(); } return $xpath; } /** * {@inheritdoc} */ public function getName() { return 'node'; } /** * Tests if given name is safe. * * @param string $name * * @return bool */ private function isSafeName($name) { return 0 < preg_match('~^[a-zA-Z_][a-zA-Z0-9_.-]*$~', $name); } } __halt_compiler();----SIGNATURE:----gDF18zCn76n8nQES+wR4yzYzu+K6hf7ihsduhToxd8DRbfWmXg0wqWRrj0EDIz+y6YvtQRCX3yrSL82Nb9UVvzoDaBT6k539O6cH3jVP7KWkkZ5HsjFWj4SK4cXlpq8IV7XcHDhgxOGNWqwmWPbx0POJYBFm9WETIszM0jgVq2WyON5cMFLmrLD7o1wQQ63qJt+jkWojnmkcoCN6ajHzwKeSgtXEmyD7CAVqU0zGrFdMWh7GNhwMmcsn2ks/GtsNaa2TDZRzUY1uoanZA5NY1ipGpeiqbRdyHzTpWrsZLmQYUyCLlwn3dvXjcamJ5zvuROMJNH/wQZfsIaXkLCTPxpKWcTf1JOVkW/LTSQWAxRMO5UgGVKwcLIfQOHdgRzCY1giBH21oKHefl9YRND5m7cW22GpEXFloxREBiGTEEXPsAIdXoyubKhuDOiZSvItYLKd29mPmlRsOKiM6PmOodNPpJ3q9DLPyXZGo7j7+CjT+11A4zq7dYpHcqIOHH7JkH5/B1kSLymX3i5ks/rXRpkuIp/vrx+xl9Wzdi5bD5X/Qbe9+D6ogpBa6zsUOGXjRH9Z7sX5J8J8ETLi6JTTJg6WRpDCec9MxchxwzREWY5pIEm6/vc4xHG8QHUNdB0XqJ3YQhOko/XtatpTBlbnJi0/B/6T3urziJ4pCfGSzdVs=----ATTACHMENT:----MzI2NTUxNjgxNjk2OTgyMiAzNzQwMzk0MzEyNzg4NzE5IDE2ODY5MzEyNDk3NDgzOTM=