Компилирует ли PHP XPath - PullRequest
       42

Компилирует ли PHP XPath

0 голосов
/ 22 мая 2018

Может кто-нибудь сказать мне, если и когда PHP компилирует выражения XPath?Было бы полезно узнать как для классов simpleXML, так и для классов DOMDocument.Я также хочу знать, где хранится скомпилированный XPath.

1 Ответ

0 голосов
/ 24 мая 2018

PHP-функциональность XML полностью основана на libxml2 библиотеке , поэтому часть ответа будет зависеть от того, как работает эта библиотека, а частично - от того, как именно PHP ее использует.

Начиная с SimpleXML, мы можем найти реализацию SimpleXMLElement->xpath() в ext / simplexml / simplexml.c .Пропустив некоторые внутренние операции, проверку типов параметров и т. Д., Первая интересная строка, которую мы находим:

if (!sxe->xpath) {
    sxe->xpath = xmlXPathNewContext((xmlDocPtr) sxe->document->ptr);
}

Таким образом, повторяющиеся выражения XPath для одного и того же SimpleXMLElement будут использовать тот же «контекст XPath», ноон не будет передан другим экземплярам.Далее мы находим, где это используется:

retval = xmlXPathEval((xmlChar *)query, sxe->xpath);

Итак, PHP вызывает функцию libxml xmlXPathEval, которая просто берет строку и контекст и немедленно ее оценивает.В руководстве libxml для xmlXPathEval` сказано:

Оценить путь расположения XPath в заданном контексте.

Возвращает: xmlXPathObjectPtr, полученный в результате оценки или NULL.вызывающая сторона должна освободить объект.

И действительно, PHP освобождает результат в конце метода:

xmlXPathFreeObject(retval);

Так что, по крайней мере, в SimpleXML нетотдельный этап компиляции, и между вызовами метода ничего не сохраняется.

Версия DOM немного сложнее, потому что она имеет видимый пользователем объект, представляющий контекст XPath, который определен в /ext/dom/xpath.c.Во-первых, конструктор устанавливает контекст, как вы могли ожидать:

PHP_METHOD(domxpath, __construct)
{
    # ...
    ctx = xmlXPathNewContext(docp);

Затем он делает некоторую магию, чтобы повторно использовать этот контекст, где это возможно, но мы еще не скомпилировали XPath это просто context , то есть "текущий узел", с которым сравниваются выражения.Определения для ->eval() или ->query() используют одну и ту же реализацию C, php_xpath_eval.Это проверяет правильность некоторого внутреннего состояния, а затем вызывает:

xpathobjp = xmlXPathEvalExpression((xmlChar *) expr, ctxp);

Это другая функция, поэтому мы можем найти ее в libxml :

Функция: xmlXPathEvalExpression Псевдоним для xmlXPathEval ().

Итак, оказывается, что в конце концов нет никакой разницы.Опять же, передается строка, возвращается результат, и функция PHP освобождает этот результат перед возвратом:

xmlXPathFreeObject(xpathobjp);

Итак, как и прежде: нет явной компиляции, и единственное, что сохраняется между вызовами, это "контекст"для выполнения выражений XPath.

Оказывается, libxml поддерживает какой-либо кэш, если он включен через xmlXPathContextSetCache:

Создает / освобождает кеш объекта в контексте XPath.При активации XPath объекты (xmlXPathObject) будут внутренне кэшироваться для повторного использования.@options: 0: Это установит кэширование объектов XPath: @value: Это установит максимальное количество объектов XPath, которые будут кэшироваться на слот. Есть 5 слотов для: набор узлов, строка, число, логические объекты и объекты misc.Используйте <0 для номера по умолчанию (100).Другие значения для @options в настоящее время не действуют. </p>

В случае SimpleXML этот кеш в любом случае не будет полезен, так как контекст отбрасывается после использования;для DOM это было бы более уместно, так как контекст - и, следовательно, кеш - будет жить так же долго, как объект PHP DOMXPath.

Мы можем копаться в реализации xmlXpathNewContext, чтобы увидеть, включен ли этот кеш по умолчанию:

#ifdef XP_DEFAULT_CACHE_ON
    if (xmlXPathContextSetCache(ret, 1, -1, 0) == -1) {
    xmlXPathFreeContext(ret);
    return(NULL);
    }
#endif

Так получается, что это опция времени компиляции - если libxml скомпилирован или загруженв вашем PHP был установлен этот флаг, когда он был скомпилирован, я полагаю, что в случае DOM XPath у вас будет некоторая степень кэширования, в пределах одного экземпляра DOMXPath` .

...