§ Код класса

<?php

libxml_use_internal_errors(true);

class xpath
{
    protected DOMDocument $dom;
    protected DOMXPath    $xpath;

    /**
     * @param  string  $content
     * @throws Exception
     */
    public function __construct(string $content)
    {
        $this->dom = new DOMDocument();

        if ($content == '') {
            throw new Exception("Content for empty string");
        }

        $this->dom->loadHTML(mb_convert_encoding($content, 'HTML-ENTITIES', 'UTF-8'));
        $this->xpath = new DOMXPath($this->dom);
        $this->dom->normalizeDocument();

        libxml_clear_errors();
        return $this;
    }

    /**
     * @desc What -- что именно искать, Where - порядковый номер или false, если надо все
     * # -- HTML-код
     * $ -- TEXT
     * @ -- Нода
     * @param $query
     * @param  null  $what
     * @param  int|null  $where
     * @return array|mixed|string|void|null
     * @throws Exception
     */
    public function query($query, $what = null, mixed $where = -1)
    {
        $rows = [];
        $result = $this->xpath->query($query);

        // Была ошибка при запросе
        if ($error = libxml_get_last_error()) {
            throw new Exception("XQuery [" . trim($error->message) . "] for: $query");
        }

        // Запрос на все поля N-го результата
        if (is_integer($what)) {
            [$where, $what] = [$what, null];
        }

        // Нет результатов
        if ($result->length === 0) {
            libxml_clear_errors();
            return [];
        }

        foreach ($result as $n => $item)
        {
            $row = [
                '@' => $item,
                '$' => $item->nodeValue,
                '#' => '',
            ];

            $dom = new DOMDocument();

            // Сканировать атрибуты
            if (is_object($item->attributes)) {
                foreach ((object)$item->attributes as $ds) {
                    $row[$ds->nodeName] = $ds->nodeValue;
                }
            }

            // HTML-код
            try {

                $dom->appendChild($dom->importNode($item, true));
                $row['#'] = preg_replace('~(^<[^>]*>|</[^>]*>$)~', '', trim(html_entity_decode($dom->saveHTML())));

            } catch (Exception) {
                $row['#'] = '';
            }

            unset($dom);

            // Выборка определенного сообщения
            if ($what !== null) {
                $row = $row[$what] ?? null;
            }

            // Был достигнут определенный номер
            if ($where === $n) {
                $rows = $row;
                break;
            } else {
                $rows[] = $row;
            }
        }

        libxml_clear_errors();
        return $rows;
    }
}