<?php
 class vB_Xml_Scanner { use vB_Trait_NoSerialize; private string $xmlfile; public function __construct(string $xmlfile) { $this->xmlfile = $xmlfile; } public function getTextFromNodeByAttribute(string $path, string $attribute) : false|string { $reader = xmlReader::open($this->xmlfile); if (!$reader) { throw new vB_Exception_Api('error_x', ['File ' . $this->xmlfile . ' not found']); } if (!$this->findNode($reader, $path, $attribute)) { return false; } return $this->getNodeText($reader); } public function getNodeAttributes(string $path, string $attribute) : array { $reader = xmlReader::open($this->xmlfile); if (!$reader) { throw new vB_Exception_Api('error_x', ['File ' . $this->xmlfile . ' not found']); } $patharray = explode('/', $path); $lastindex = count($patharray) - 1; $values = []; $reader->read(); while ($reader->nodeType != XmlReader::NONE) { $pathindex = $reader->depth + 1; if ($patharray[$pathindex] == $reader->name) { if ($pathindex == $lastindex) { $value = $reader->getAttribute($attribute); if ($value !== null) { $values[] = $value; } $reader->next(); continue; } else { $reader->read(); continue; } } $reader->next(); } return $values; } private function findNode(xmlReader $reader, string $path, string $filter) : bool { $patharray = explode('/', $path); $lastindex = count($patharray) - 1; [$attribute, $value] = explode('=', $filter); $reader->read(); while ($reader->nodeType != XmlReader::NONE) { $pathindex = $reader->depth + 1; if ($patharray[$pathindex] == $reader->name) { if ($pathindex == $lastindex) { if ($reader->getAttribute($attribute) == $value) { return true; } } else { $reader->read(); continue; } } $reader->next(); } return false; } private function getNodeText(xmlReader $reader) : string { $depth = $reader->depth; $name = $reader->name; $text = ''; while ($reader->read()) { if ($reader->nodeType == XmlReader::TEXT) { if (trim($reader->value) != '') { $text .= $reader->value; } } else if ($reader->nodeType == XmlReader::CDATA) { $text .= $reader->value; } if ($reader->nodeType == XmlReader::END_ELEMENT AND $reader->name == $name AND $reader->depth == $depth) { break; } } return $text; } } 