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` .