The main difference to DOMXpath::evaluate() is the handling of the third
argument. Namespace registration can be changed using the property and
is disabled by default.
/** * @param \DOMElement $node * @param \stdClass|array $attributes * @param Xpath $xpath * @return array */ private function getNodesArray(\DOMElement $node, $attributes, $xpath) { $result = []; foreach ($attributes as $name => $value) { $child = new \stdClass(); $child->{$name} = $value; $result[] = $child; } foreach ($xpath->evaluate('*|text()[normalize-space(.) != ""]', $node) as $childNode) { /** @var \DOMElement|\DOMText|\DOMCdataSection $childNode */ if ($childNode instanceof \DOMElement) { $child = new \stdClass(); $child->{$childNode->nodeName} = $this->getNodes($childNode); $result[] = $child; } elseif (!$childNode->isWhitespaceInElementContent()) { $result[] = $childNode->nodeValue; } } return $result; }
/** * @param \stdClass $target * @param \DOMElement $node * @param Xpath $xpath */ protected function addNamespaces(\stdClass $target, \DOMElement $node, Xpath $xpath) { if ($node->namespaceURI != '' && $node->prefix === '') { if (!isset($target->{'@xmlns'})) { $target->{'@xmlns'} = new \stdClass(); } $target->{'@xmlns'}->{'$'} = $node->namespaceURI; } foreach ($xpath->evaluate('namespace::*', $node) as $namespace) { if ($namespace->localName === 'xml' || $namespace->localName === 'xmlns') { continue; } if (!isset($target->{'@xmlns'})) { $target->{'@xmlns'} = new \stdClass(); } if ($namespace->nodeName !== 'xmlns') { $target->{'@xmlns'}->{$namespace->localName} = $namespace->namespaceURI; } } }
/** * @param \DOMElement $node * @return array */ private function getAllNamespaces(\DOMElement $node) { $xpath = new Xpath($node->ownerDocument); $result = []; foreach ($xpath->evaluate('namespace::*', $node) as $namespace) { if ($namespace->nodeName !== 'xmlns:xml' && $namespace->nodeName !== 'xmlns:xmlns') { $result[$namespace->nodeName] = $namespace->namespaceURI; } } return $result; }