Get a list of parameters from given XPath expression

@param  DOMNode  $node Context node
@param  string   $expr XPath expression
@return string[]
439833
protected static function getParametersFromExpression(DOMNode $node, $expr)
	{
		$varNames   = XPathHelper::getVariables($expr);
		$paramNames = [];
		$xpath      = new DOMXPath($node->ownerDocument);
		foreach ($varNames as $name)
		{
			// Test whether this is the name of a local variable
			$query = 'ancestor-or-self::*/preceding-sibling::xsl:variable[@name="' . $name . '"]';
			if (!$xpath->query($query, $node)->length)
			{
				$paramNames[] = $name;
			}
		}

		return $paramNames;
	}
526530
public static function getAllElementsByXpath($node, $xpath_query, $namespaces = array())
    {
        if(is_a($node, 'DOMDocument'))
        {
            $xpath = new DOMXPath($node);
        }
        elseif(is_a($node, 'DOMNode'))
        {
            $xpath = new DOMXPath($node->ownerDocument);
        }
        else
        {
            return null;
        }

        foreach($namespaces as $prefix => $namespaceURI)
        {
            $xpath->registerNamespace($prefix, $namespaceURI);
        }

        $node_list = $xpath->query($xpath_query, $node);

        return $node_list;
    }
815240
public function processNode(Node $node, Scope $scope): array
    {
        if (0 === \count($node->params)) {
            return [];
        }

        $params = \array_filter($node->params, static function (Node\Param $node): bool {
            return $node->type instanceof Node\NullableType;
        });

        if (0 === \count($params)) {
            return [];
        }

        $methodName = $node->name->toString();

        /** @var Reflection\ClassReflection $classReflection */
        $classReflection = $scope->getClassReflection();

        if ($classReflection->isAnonymous()) {
            return \array_map(static function (Node\Param $node) use ($methodName): string {
                /** @var Node\Expr\Variable $variable */
                $variable = $node->var;

                /** @var string $parameterName */
                $parameterName = $variable->name;

                return \sprintf(
                    'Method %s() in anonymous class has parameter $%s with a nullable type declaration.',
                    $methodName,
                    $parameterName
                );
            }, $params);
        }

        $className = $classReflection->getName();

        return \array_map(static function (Node\Param $node) use ($className, $methodName): string {
            /** @var Node\Expr\Variable $variable */
            $variable = $node->var;

            /** @var string $parameterName */
            $parameterName = $variable->name;

            return \sprintf(
                'Method %s::%s() has parameter $%s with a nullable type declaration.',
                $className,
                $methodName,
                $parameterName
            );
        }, $params);
    }
1210448
function select( $expr ) {

        $clone = clone $this;

        if ( $clone->select === null ) {

            $clone->select = func_get_args();

        } else {

            $clone->select = array_merge( $clone->select, func_get_args() );

        }

        return $clone;

    }
122320
public static function fromExpression(ExpressionNode $expr) {
    $not = new static();
    $not->addChild(Token::not(), 'operator');
    /** @var \Pharborist\Node $expr */
    $not->addChild($expr->remove(), 'operand');
    return $not;
  }
514386
function _select (node, expr) {
        var
            resultSet,
            nodeSet = [node];
        while (expr) {
            resultSet = [];
            _test(nodeSet, expr, resultSet);
            if (0 === resultSet.length) {
                return [];
            }
            nodeSet = resultSet;
            if (expr.filter) {
                resultSet = [];
                _each(nodeSet, _filter, expr.filter, resultSet);
                if (0 === resultSet.length) {
                    return [];
                }
                nodeSet = resultSet;
            }
            expr = expr.then;
        }
        return resultSet;
    }
201542
private function parseXmlValue(\DOMNode $node, array $context = [])
    {
        if (!$node->hasChildNodes()) {
            return $node->nodeValue;
        }

        if (1 === $node->childNodes->length && \in_array($node->firstChild->nodeType, [XML_TEXT_NODE, XML_CDATA_SECTION_NODE])) {
            return $node->firstChild->nodeValue;
        }

        $value = [];
        $decoderIgnoredNodeTypes = $context[self::DECODER_IGNORED_NODE_TYPES] ?? $this->defaultContext[self::DECODER_IGNORED_NODE_TYPES];
        foreach ($node->childNodes as $subnode) {
            if (\in_array($subnode->nodeType, $decoderIgnoredNodeTypes, true)) {
                continue;
            }

            $val = $this->parseXml($subnode, $context);

            if ('item' === $subnode->nodeName && isset($val['@key'])) {
                $value[$val['@key']] = $val['#'] ?? $val;
            } else {
                $value[$subnode->nodeName][] = $val;
            }
        }

        $asCollection = $context[self::AS_COLLECTION] ?? $this->defaultContext[self::AS_COLLECTION];
        foreach ($value as $key => $val) {
            if (!$asCollection && \is_array($val) && 1 === \count($val)) {
                $value[$key] = current($val);
            }
        }

        return $value;
    }
667671
public function getType($expr)
	{
		$match = $this->getMatch($expr);

		return (isset($match, $this->matchGroup[$match[0]])) ? $this->matchGroup[$match[0]] : null;
	}
541892
protected function parseOptions(\SimpleXMLElement $node)
    {
        $options = [];
        /** @var \SimpleXMLElement $option */
        foreach ($node->option as $option) {
            if ($option->count() > 0) {
                if (count($option->value) > 0) {
                    $value = $this->parseValues($option);
                } else {
                    $value = [];
                }
            } else {
                $value = XmlUtils::phpize($option);
                if (is_string($value)) {
                    $value = trim($value);
                }
            }

            $options[(string) $option['name']] = $value;
        }

        return $options;
    }
242157
protected function getQueryNodes(AbstractNode $node): array
    {
        $methodPostfix = $node->findChildrenOfType('MethodPostfix');
        $classOrInterfaceReference = $node->findChildrenOfType('ClassOrInterfaceReference');

        return array_merge($methodPostfix, $classOrInterfaceReference);
    }
1001084
public function addNotExistsToQueryCondition(Expr $expr)
    {
        $expr->attr($this->getHashKey()->getPropertyMetadata()->name)->exists(false);
    }
682205
protected function parseValues(\SimpleXMLElement $node)
    {
        $values = [];

        foreach ($node->value as $item) {
            if ($item->count() > 0) {
                $value = $this->parseValues($item);
            } else {
                $value = trim($item);
            }

            if (isset($item['key'])) {
                $values[(string) $item['key']] = $value;
            } else {
                $values[] = $value;
            }
        }

        return $values;
    }
888789
protected function checkAttributeExpression(DOMNode $node, Tag $tag, $expr)
	{
		preg_match_all('(@([-\\w]+))', $expr, $matches);
		foreach ($matches[1] as $attrName)
		{
			$this->checkAttribute($node, $tag, $attrName);
		}
	}
1060035
private function exprList() {
    $node = new CommaListNode();
    do {
      $node->addChild($this->expr());
    } while ($this->tryMatch(',', $node));
    return $node;
  }
334653
public static function getAllValuesByXpath($node, $xpath_query, $namespaces = array())
    {
        $node_list = XMLTool :: getAllElementsByXpath($node, $xpath_query, $namespaces);

        $values = array();

        if (isset($node_list))
        {
            foreach ($node_list as $node_found)
            {
                $values[] = $node_found->nodeValue;
            }
        }

        return $values;
    }
676822
protected function checkExpression(DOMNode $node, $expr, Tag $tag)
	{
		$this->checkContext($node);

		if (preg_match('/^\\$(\\w+)$/', $expr, $m))
		{
			// Either this expression came from a variable that is considered safe, or it's a
			// stylesheet parameters, which are considered safe by default
			$this->checkVariable($node, $tag, $m[1]);
		}
		elseif (preg_match('/^@[-\\w]+(?:\\s*\\|\\s*@[-\\w]+)*$/', $expr))
		{
			$this->checkAttributeExpression($node, $tag, $expr);
		}
		elseif (!$this->isExpressionSafe($expr))
		{
			throw new UnsafeTemplateException("Cannot assess the safety of expression '" . $expr . "'", $node);
		}
	}
1112768
public static function getParametersFromXSL($xsl)
	{
		$paramNames = [];
		$xpath      = new DOMXPath(TemplateLoader::load($xsl));

		// Start by collecting XPath expressions in XSL elements
		$query = '//xsl:*/@match | //xsl:*/@select | //xsl:*/@test';
		foreach ($xpath->query($query) as $attribute)
		{
			$expr        = $attribute->value;
			$paramNames += array_flip(self::getParametersFromExpression($attribute, $expr));
		}

		// Collect XPath expressions in attribute value templates
		$query = '//*[namespace-uri() != "' . self::XMLNS_XSL . '"]/@*[contains(., "{")]';
		foreach ($xpath->query($query) as $attribute)
		{
			foreach (AVTHelper::parse($attribute->value) as $token)
			{
				if ($token[0] === 'expression')
				{
					$expr        = $token[1];
					$paramNames += array_flip(self::getParametersFromExpression($attribute, $expr));
				}
			}
		}

		// Sort the parameter names and return them in a list
		ksort($paramNames);

		return array_keys($paramNames);
	}