繁体   English   中英

PHP DomDocument,XSLTProcessor的重用,是否稳定/安全?

[英]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需要了解导入的数据的方式和发生的情况:

  1. XSLTProcessor :: importStylesheet接受DOMDocumentSimpleXMLElement对象。
  2. 导入时会发生的事情(从409行源代码中, docpimportStylesheet参数)

     //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); 
  3. importStylesheet之后,您可以使用$ stylesheet对象执行任何操作-由于它使用$ stylesheet的副本,因此不会影响XSLTProcessor的工作。 但是您无法刷新或更新$ stylesheet,而无需再次调用importStylesheet

XSLTProcessor::transformToDocphp_xsl_apply_stylesheet来自同一行的477行)和其他transform方法有关。 他们每个人分配他们的输出类型(在XSLTProcessor::transformToDoc情况下为DOMDocument),并使用内部sheetp对象(在importStylesheet创建)来转换数据。

评论后编辑

  1. 关于“何时”和/或“为什么”重用条件的某些说法无效。 重用是有效的,建议您在每次需要进行transformTo之后再使用一次。 如果stylesheep在大型样式表上使用xsl:key ,则应该重用,因为会额外遍历XML节点。
  2. 仅缓存XSLTProcessor对象没有任何意义-该对象的构造方法不分配任何内容。 XSLproc_reuse2是有意义的,应该使用。 您缓存$ stylesheet复制过程并遍历xsl:key用法。 不是指针,而是所有对象及其内部。

让我们再来s some more words about how the transformToDoc`的工作方式:

  1. 分配新的DOMDocument对象。
  2. 如果$ stylesheet具有xsl:key,则复制$ doc参数。
  3. 使用来自libxslt xsltNewTransformContextxsltApplyStylesheetUser
  4. 返回DOMDocument

XSLTProcessorlibxslt没有任何惩罚代码,导致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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM