[英]PHP DomDocument, reuse of XSLTProcessor, it is stable/secure?
我正在使用下面的功能,但不确定它是否始终安全...是吗? 那里没有DOM内存或“残余XSLT”?
function XSLproc_reuse($domXsl) {
static $XSLproc=NULL;
if (!$XSLproc)
$XSLproc = new XSLTProcessor();
return $XSLproc->importStylesheet($domXsl); // STABLE?
}
将来没有“意外副作用”吗?
PS:我的XSLT处理过程中存在一些奇怪的错误...因此,在此处发布一个(或多个)假设,以检查是否可以或必须避免。 这在XPath中更加明显,请参见其他相关问题 。
重用更多处理表(我在库中使用过)的另一种方法是也重用导入的XSLT:
function XSLproc_reuse2($nameOrDomXsl='', $domXsl=NULL) {
static $XSLproc=NULL;
static $name='';
if (!$XSLproc)
$XSLproc = new XSLTProcessor();
// else reune of the already initialized $XSLproc.
if (is_object($nameOrDomXsl))
return $XSLproc->importStylesheet($nameOrDomXsl); // STABLE?
elseif ($nameOrDomXsl==$name);
return $XSLproc; // imported in the last call, STABLE?
else { // recording for future reuse:
$name = $nameOrDomXsl;
return $XSLproc->importStylesheet($domXsl);
}
}
要了解此问题,重要的是要了解XSLTProcessor如何在内部存储数据以及调用XSLTProcessor::importStylesheet
之后会发生什么。 实现此类的代码位于php源代码的\\ext\\xsl\\xsltprocessor.c
。
说明将使事情简化一些-用纯PHP'c'编写。 什么是在一个PHP对象-来讲с
只是功能上全球范围内进行操作。
Web需要了解导入的数据的方式和发生的情况:
DOMDocument
或SimpleXMLElement
对象。 导入时会发生的事情(从409行源代码中, docp
是importStylesheet
参数)
//php_libxml_import_node is (in the \\ext\\libxml\\libxml.c) just get //the real `xmlNodePtr` XMLlib2 object pointer by php object pointer. nodep = php_libxml_import_node(docp TSRMLS_CC); if (nodep) { doc = nodep->doc; } if (doc == NULL) { php_error(E_WARNING, "Invalid Document"); RETURN_FALSE; } //Next lines is an original comments and call of `xmlCopyDoc` which makes copy // of your stylesheet. The main lines in my answer. /* libxslt uses _private, so we must copy the imported stylesheet document otherwise the node proxies will be a mess */ newdoc = xmlCopyDoc(doc, 1); .... //Here we create internal stylesheet object with libxslt function.
sheetp = xsltParseStylesheetDoc(newdoc);
...
//And some lines later store them to internal variables for this //XSLTProcessor class instance. php_xsl_set_object(id, sheetp TSRMLS_CC);
在importStylesheet
之后,您可以使用$ stylesheet对象执行任何操作-由于它使用$ stylesheet的副本,因此不会影响XSLTProcessor
的工作。 但是您无法刷新或更新$ stylesheet,而无需再次调用importStylesheet
。
XSLTProcessor::transformToDoc
( php_xsl_apply_stylesheet
来自同一行的477行)和其他transform
方法有关。 他们每个人分配他们的输出类型(在XSLTProcessor::transformToDoc
情况下为DOMDocument),并使用内部sheetp
对象(在importStylesheet
创建)来转换数据。
评论后编辑
transformTo
之后再使用一次。 如果stylesheep在大型样式表上使用xsl:key ,则应该重用,因为会额外遍历XML节点。 XSLproc_reuse2
是有意义的,应该使用。 您缓存$ stylesheet复制过程并遍历xsl:key用法。 不是指针,而是所有对象及其内部。 让我们再来s some more words about how the
transformToDoc`的工作方式:
DOMDocument
对象。 libxslt
xsltNewTransformContext
和xsltApplyStylesheetUser
。 DOMDocument
XSLTProcessor
或libxslt
没有任何惩罚代码,导致XSLTProcessor
重用错误。 在xslcache
0.7.2之前,我尝试使用此项目并对其进行调整以使其与外部站点一起使用。 有我的经验。 当时,我们将XSLT用作具有大型XSLT模板的模板引擎(约3-5mb的最小化代码)。 在这种情况下, importStylesheet
的缓存会大大提高性能。 但是没有任何机会可以缓存transformToDoc
结果-每次调用它时, libxslt
都会使用内存中的两个准备好的对象进行dom操作,并为您提供新的对象。
使用静态定义了全局状态,即定义为“不稳定”。 可以在程序中的任何位置进行更改。 使用对象,您可以获取局部状态(在对象实例内部)。 我也建议使用数组。 因此它可以为不同的文件存储多个处理器。
class XsltFactory {
private $_processors = array();
public function get($file) {
if (!isset($this->_processors[$file])) {
$xslDom = new DOMDocument();
$xslDom->load($file);
$xslProc = new XSLTProcessor();
$xslProc->importStylesheet($xslDom);
return $this->_processors[$file] = $xslProc;
}
return $this->_processors[$file];
}
}
$xsltFactory = new XsltFactory();
var_dump(
htmlspecialchars(
$xsltFactory->get($template)->transformToDoc($xmlDom)->saveXml()
)
);
提高性能的更好解决方案是xslcache 。 它将$xslt->importStyleSheet($filename)
的结果缓存在进程内部。 如果该过程被重用,则编译后的xsl也将被重用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.