Parse pipelines from a bucket.

@param \DOMXPath $xpath    XPath access to the document parsed.
@param \DOMNode  $rootNode Aggregation node to be parsed for pipeline aggregations.

@return array
194900
private function parsePipelines(\DOMXPath $xpath, \DOMNode $rootNode)
    {
        $pipelines = [];

        foreach ($xpath->query(self::PIPELINES_PATH, $rootNode) as $pipelineNode) {
            $pipeline = [];
            foreach ($pipelineNode->attributes as $attribute) {
                $pipeline[$attribute->name] = $attribute->value;
            }
            $pipeline['bucketsPath'] = $this->parsePipelineBucketsPath($xpath, $pipelineNode);
            $pipelines[$pipeline['name']] = $pipeline;
        }

        return $pipelines;
    }
1132691
private function loadType(\DOMXPath $xpath, \DOMNode $node, &$tags)
    {
        $result = $this->loadValues($xpath, $node, ['name']);

        $result['meta'] = $this->loadMeta($xpath, $node);

        $propertiesNode = $xpath->query('x:properties', $node)->item(0);
        $result['properties'] = $this->loadProperties($tags, $xpath, $propertiesNode);

        return $result;
    }
923774
private function getNodesToExclude(\DOMXPath $xPath)
    {
        $excludedNodes = [];
        foreach (\array_keys($this->excludedSelectors) as $selectorToExclude) {
            try {
                $matchingNodes = $xPath->query($this->cssSelectorConverter->toXPath($selectorToExclude));
            } catch (SyntaxErrorException $e) {
                if ($this->debug) {
                    throw $e;
                }
                continue;
            }
            foreach ($matchingNodes as $node) {
                $excludedNodes[] = $node;
            }
        }

        return $excludedNodes;
    }
1156704
protected function convertNode(\DOMNode $node, $path = '')
    {
        $output = [];
        if ($node->nodeType == XML_ELEMENT_NODE) {
            $nodeName = $this->parseNodeName($node);
            $output[$nodeName] = $this->parseNodeData($node, $path);
        } elseif ($node->nodeType == XML_CDATA_SECTION_NODE
            || $node->nodeType == XML_TEXT_NODE && trim($node->nodeValue) != '') {
            return $node->nodeValue;
        }

        return $output;
    }
926957
private function loadParams($path, \DOMXPath $xpath, \DOMNode $context = null)
    {
        $result = [];

        /** @var \DOMElement $node */
        foreach ($xpath->query($path, $context) as $node) {
            $result[] = $this->loadParam($xpath, $node);
        }

        return $result;
    }
1021995
protected function process(\DOMDocument $xmlDocument)
    {
        $xPath = new \DOMXPath($xmlDocument);
        $this->clearAllCaches();
        $this->purgeVisitedNodes();
        set_error_handler([$this, 'handleXpathQueryWarnings'], E_WARNING);

        $this->normalizeStyleAttributesOfAllNodes($xPath);

        // grab any existing style blocks from the html and append them to the existing CSS
        // (these blocks should be appended so as to have precedence over conflicting styles in the existing CSS)
        $allCss = $this->css;
        if ($this->isStyleBlocksParsingEnabled) {
            $allCss .= $this->getCssFromAllStyleNodes($xPath);
        }

        $cssParts = $this->splitCssAndMediaQuery($allCss);
        $excludedNodes = $this->getNodesToExclude($xPath);
        $cssRules = $this->parseCssRules($cssParts['css']);
        foreach ($cssRules as $cssRule) {
            // There's no real way to test "PHP Warning" output generated by the following XPath query unless PHPUnit
            // converts it to an exception. Unfortunately, this would only apply to tests and not work for production
            // executions, which can still flood logs/output unnecessarily. Instead, Emogrifier's error handler should
            // always throw an exception and it must be caught here and only rethrown if in debug mode.
            try {
                // \DOMXPath::query will always return a DOMNodeList or an exception when errors are caught.
                $nodesMatchingCssSelectors = $xPath->query($this->translateCssToXpath($cssRule['selector']));
            } catch (\InvalidArgumentException $e) {
                if ($this->debug) {
                    throw $e;
                }
                continue;
            }

            /** @var \DOMElement $node */
            foreach ($nodesMatchingCssSelectors as $node) {
                if (in_array($node, $excludedNodes, true)) {
                    continue;
                }
                // if it has a style attribute, get it, process it, and append (overwrite) new stuff
                if ($node->hasAttribute('style')) {
                    // break it up into an associative array
                    $oldStyleDeclarations = $this->parseCssDeclarationsBlock($node->getAttribute('style'));
                } else {
                    $oldStyleDeclarations = [];
                }
                $newStyleDeclarations = $this->parseCssDeclarationsBlock($cssRule['declarationsBlock']);
                $node->setAttribute(
                    'style',
                    $this->generateStyleStringFromDeclarationsArrays($oldStyleDeclarations, $newStyleDeclarations)
                );
            }
        }

        if ($this->isInlineStyleAttributesParsingEnabled) {
            $this->fillStyleAttributesWithMergedStyles();
        }

        if ($this->shouldMapCssToHtml) {
            $this->mapAllInlineStylesToHtmlAttributes($xPath);
        }

        if ($this->shouldKeepInvisibleNodes) {
            $this->removeInvisibleNodes($xPath);
        }

        $this->removeImportantAnnotationFromAllInlineStyles($xPath);

        $this->copyCssWithMediaToStyleNode($xmlDocument, $xPath, $cssParts['media']);

        restore_error_handler();
    }
826532
private function filterRelativeXPath($xpath)
    {
        $prefixes = $this->findNamespacePrefixes($xpath);

        $crawler = $this->createSubCrawler(null);

        foreach ($this->nodes as $node) {
            $domxpath = $this->createDOMXPath($node->ownerDocument, $prefixes);
            $crawler->add($domxpath->query($xpath, $node));
        }

        return $crawler;
    }
1102937
private function parseDatasources(\DOMXPath $xpath, \DOMNode $typeRootNode)
    {
        $datasources = [];

        foreach ($xpath->query(self::DATASOURCES_PATH, $typeRootNode) as $datasourceNode) {
            $datasources[$datasourceNode->getAttribute('name')] = $datasourceNode->nodeValue;
        }

        return $datasources;
    }
503320
private function postProcess(\DOMXPath $xPath)
    {
        if ($this->shouldMapCssToHtml) {
            $this->mapAllInlineStylesToHtmlAttributes($xPath);
        }
        if ($this->shouldRemoveInvisibleNodes) {
            $this->removeInvisibleNodes($xPath);
        }
    }
155408
public function convert(DOMDocument $xmlDoc)
    {
        $xpath = new DOMXPath($xmlDoc);

        $elements = $xpath->query('//link|//embed|//embed-inline');

        /** @var \DOMElement $element */
        foreach ($elements as $element) {
            $location = null;

            if ($this->elementHasAttribute($element, 'object_id')) {
                try {
                    $contentInfo = $this->contentService->loadContentInfo(
                        $this->getElementAttribute($element, 'object_id')
                    );
                    $location = $this->locationService->loadLocation($contentInfo->mainLocationId);
                } catch (APINotFoundException $e) {
                    if ($this->logger) {
                        $this->logger->warning(
                            'While generating links for xmltext, could not locate ' .
                            'Content object with ID ' . $this->getElementAttribute($element, 'object_id')
                        );
                    }
                } catch (APIUnauthorizedException $e) {
                    if ($this->logger) {
                        $this->logger->notice(
                            'While generating links for xmltext, unauthorized to load ' .
                            'Content object with ID ' . $this->getElementAttribute($element, 'object_id')
                        );
                    }
                }
            }

            if ($this->elementHasAttribute($element, 'node_id')) {
                try {
                    $location = $this->locationService->loadLocation(
                        $this->getElementAttribute($element, 'node_id')
                    );
                } catch (APINotFoundException $e) {
                    if ($this->logger) {
                        $this->logger->warning(
                            'While generating links for xmltext, could not locate ' .
                            'Location with ID ' . $this->getElementAttribute($element, 'node_id')
                        );
                    }
                } catch (APIUnauthorizedException $e) {
                    if ($this->logger) {
                        $this->logger->notice(
                            'While generating links for xmltext, unauthorized to load ' .
                            'Location with ID ' . $this->getElementAttribute($element, 'node_id')
                        );
                    }
                }
            }

            if ($location !== null) {
                $element->setAttribute('url', $this->urlAliasRouter->generate($location));
            }

            // Copy temporary URL if it exists and is not set at this point
            if (!$element->hasAttribute('url') && $element->hasAttribute(EmbedLinking::TEMP_PREFIX . 'url')) {
                $element->setAttribute('url', $element->getAttribute(EmbedLinking::TEMP_PREFIX . 'url'));
            }

            if ($this->elementHasAttribute($element, 'anchor_name')) {
                $anchor = '#' . $this->getElementAttribute($element, 'anchor_name');
                if (strpos($element->getAttribute('url'), $anchor) === false) {
                    $element->setAttribute(
                        'url',
                        $element->getAttribute('url') . '#' .
                        $this->getElementAttribute($element, 'anchor_name')
                    );
                }
            }
        }
    }
329394
protected function getFormField($xpath)
    {
        $fieldNode = $this->getCrawlerNode($this->getFilteredCrawler($xpath));
        $fieldName = str_replace('[]', '', $fieldNode->getAttribute('name'));

        $formNode = $this->getFormNode($fieldNode);
        $formId = $this->getFormNodeId($formNode);

        if (!isset($this->forms[$formId])) {
            $this->forms[$formId] = new Form($formNode, $this->getCurrentUrl());
        }

        if (is_array($this->forms[$formId][$fieldName])) {
            return $this->forms[$formId][$fieldName][$this->getFieldPosition($fieldNode)];
        }

        return $this->forms[$formId][$fieldName];
    }
1125530
private function parseXmlAttributes(\DOMNode $node, array $context = []): array
    {
        if (!$node->hasAttributes()) {
            return [];
        }

        $data = [];
        $typeCastAttributes = (bool) ($context[self::TYPE_CASE_ATTRIBUTES] ?? $this->defaultContext[self::TYPE_CASE_ATTRIBUTES]);

        foreach ($node->attributes as $attr) {
            if (!is_numeric($attr->nodeValue) || !$typeCastAttributes) {
                $data['@'.$attr->nodeName] = $attr->nodeValue;

                continue;
            }

            if (false !== $val = filter_var($attr->nodeValue, FILTER_VALIDATE_INT)) {
                $data['@'.$attr->nodeName] = $val;

                continue;
            }

            $data['@'.$attr->nodeName] = (float) $attr->nodeValue;
        }

        return $data;
    }
1000620
public static function getFirstElementByXpath($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);

        if ($node_list->length > 0)
        {
            return $node_list->item(0);
        }
        else
        {
            return null;
        }
    }
305280
public function getDocument($document, $rootNode)
	{
		$documentName = self::getName($document);
		$xpath = self::getXPath($document);

		if (!self::existsDocument($documentName))
		{
			throw new NotFoundException("Document " . $document . " doesn't exists in repository", 600);
		}

		$documentName = self::getFullFileName($documentName);
		
		if ($xpath == "")
		{
			$doc = XmlUtil::CreateXmlDocumentFromFile($documentName);
		}
		else
		{
			$doc = XmlUtil::CreateXmlDocumentFromStr("< $rootNode />", false);
			$source = XmlUtil::CreateXmlDocumentFromFile($documentName);
			
			$DocXpath = new DOMXPath($source);
			$nodes = $DocXpath->query($xpath);

			foreach ($nodes as $node)
			{
				$newNode = $doc->importNode($node);

				$doc->documentElement->appendChild($newNode);
			}

		}

		return $doc;
	}
91439
protected function findElementXpaths($xpath) {
    $elements = $this->browser->find("xpath", $xpath);
    $nodeXPaths = array();

    if (!isset($elements["ids"])) {
      return array();
    }

    foreach ($elements["ids"] as $i => $elementId) {
      $nodeXPaths[] = sprintf('(%s)[%d]', $xpath, $i + 1);
    }
    return $nodeXPaths;
  }
1361310
private function loadParam(\DOMXPath $xpath, \DOMNode $node)
    {
        $result = [
            'name' => $this->getValueFromXPath('@name', $xpath, $node),
            'type' => $this->getValueFromXPath('@type', $xpath, $node, 'string'),
            'meta' => $this->loadMeta($xpath, $node),
        ];

        switch ($result['type']) {
            case 'collection':
                $result['value'] = $this->loadParams('x:param', $xpath, $node);
                break;
            default:
                $result['value'] = $this->getValueFromXPath('@value', $xpath, $node);
                break;
        }

        return $result;
    }
554098
public static function parse($html, $xpath) {
		$doc = new \DOMDocument();
		$doc->loadHTML($html);
		$domxpath = new \DOMXPath($doc);
		$node = $domxpath->evaluate($xpath)->item(0);

		return new static($node);
	}