有人能告诉我PHP是否以及何时编译XPath表达式?知道simpleXML和DOMDocument类会很有用。我还想知道编译的XPath的存储位置。
答案 0 :(得分:1)
PHP的XML功能都建立在the libxml2
library之上,因此部分答案将取决于该库的工作方式,以及PHP如何使用它。
从SimpleXML开始,我们可以在ext/simplexml/simplexml.c中找到SimpleXMLElement->xpath()
的实现。跳过一些内部管理,检查参数类型等,我们发现的第一个有趣的行是:
if (!sxe->xpath) {
sxe->xpath = xmlXPathNewContext((xmlDocPtr) sxe->document->ptr);
}
因此,在同一SimpleXMLElement
上重复的XPath表达式将使用相同的" XPath上下文",但它不会与其他实例共享。再往下,我们找到了使用它的地方:
retval = xmlXPathEval((xmlChar *)query, sxe->xpath);
因此PHP调用了一个libxml函数xmlXPathEval
,它只接受一个字符串和一个上下文,并立即对其进行求值。 libxml manual for xmlXPathEval`说:
在给定的上下文中评估XPath位置路径。
返回:评估产生的xmlXPathObjectPtr或NULL。调用者必须释放该对象。
实际上,PHP会在方法结束时释放该结果:
xmlXPathFreeObject(retval);
因此,至少在SimpleXML中,没有单独的编译步骤,并且在对方法的调用之间不存储任何内容。
DOM版本有点复杂,因为它有一个表示XPath上下文的用户可见对象,该对象在/ext/dom/xpath.c
中定义。首先,构造函数设置上下文,如您所料:
PHP_METHOD(domxpath, __construct)
{
# ...
ctx = xmlXPathNewContext(docp);
然后尽可能重用这个上下文,但是我们还没有编译任何 XPath ,这只是 context ,即& #34;当前节点"比较表达式。 ->eval()
或->query()
的定义使用相同的C实现php_xpath_eval
。这检查一些内部状态是否正确,然后调用:
xpathobjp = xmlXPathEvalExpression((xmlChar *) expr, ctxp);
这是一个不同的功能,所以我们可以look it up in libxml:
功能:xmlXPathEvalExpression xmlXPathEval()的别名。
所以,事实证明,毕竟没有区别。同样,它传递了一个字符串,返回一个结果,PHP函数在返回之前释放了该结果:
xmlXPathFreeObject(xpathobjp);
所以,和以前一样:没有明确的编译,并且在调用之间存储的唯一内容是" context"用于运行XPath表达式。
事实证明,如果通过xmlXPathContextSetCache
启用了libxml 支持某种缓存:
在XPath上下文中创建/释放对象缓存。如果激活XPath对象(xmlXPathObject)将在内部缓存以供重用。 @options:0:这将设置XPath对象缓存:@value:这将设置每个槽缓存的最大XPath对象数有5个槽:node-set,string,number,boolean和misc对象。使用< 0表示默认数字(100)。 @options的其他值目前没有效果。
对于SimpleXML,此缓存无论如何都不会有用,因为上下文在使用后被丢弃;对于DOM,它会更相关,因为上下文 - 因此缓存 - 只要与PHP DOMXPath
对象一样长。
我们可以dig into the implementation of xmlXpathNewContext
查看默认情况下是启用还是禁用此缓存:
#ifdef XP_DEFAULT_CACHE_ON
if (xmlXPathContextSetCache(ret, 1, -1, 0) == -1) {
xmlXPathFreeContext(ret);
return(NULL);
}
#endif
所以事实证明这是编译时选项 - 如果编译或加载到PHP中的libxml
在编译时设置了这个标志,我相信你会,在DOM XPath的情况下,在单个DOMXPath`实例中有一定程度的缓存,。