本文介绍了在DomDocument中,复用DOMXpath,是否稳定?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用下面的功能,但不确定它是否始终稳定/安全... 是吗?

I am using the function below, but not sure about it is always stable/secure... Is it?

重用部分 DOMXpath 准备过程"何时以及谁是稳定/安全的?

简化XPath query() 方法的使用我们可以采用一个函数,用静态变量记住最后一次调用,

To simlify the use of the XPath query() method we can adopt a function that memorizes the last calls with static variables,

   function DOMXpath_reuser($file) {
      static $doc=NULL;
      static $docName='';
      static $xp=NULL;
      if (!$doc)
                $doc = new DOMDocument();
      if ($file!=$docName) {
                $doc->loadHTMLFile($file);
                $xp = NULL;
      }
      if (!$xp) 
                $xp = new DOMXpath($doc);
      return $xp;  // ??RETURNED VALUES ARE ALWAYS STABLE??
   }

目前的问题类似于关于 XSLTProcessor 重用的另一个.在这两个问题中,该问题都可以概括为使用 LibXML2 作为 DomDocument 实现的任何语言或框架.


The present question is similar to this other one about XSLTProcessor reuse.In both questions the problem can be generalized for any language or framework that use LibXML2 as DomDocument implementation.

还有另一个相关问题:如何刷新"LibXML2 的 DOMDocument 实例?

重用很常见(示例):

   $f = "my_XML_file.xml";
   $elements = DOMXpath_reuser($f)->query("//*[@id]");
   // use elements to get information
   $elements = DOMXpath_reuser($f)->("/html/body/div[1]");
   // use elements to get information

但是,如果您执行removeChildreplaceChild 等操作(示例),

But, if you do something like removeChild, replaceChild, etc. (example),

   $div = DOMXpath_reuser($f)->query("/html/body/div[1]")->item(0);  //STABLE
   $div->parentNode->removeChild($div);                // CHANGES DOM
   $elements = DOMXpath_reuser($f)->query("//div[@id]"); // INSTABLE! !!

可能会发生奇怪的事情,并且查询无法按预期工作!!

extrange things can be occur, and the queries not works as expected!!

  • 何时(哪些 DOMDocument 方法会影响 XPath?)
  • 为什么我们不能使用normalizeDocument刷新 DOM"(存在?)?
  • 只有一个新的 DOMXpath($doc);"总是安全的吗?还需要重新加载 $doc 吗?
  • When (what DOMDocument methods affect XPath?)
  • Why we can not use something like normalizeDocument to "refresh DOM" (exist?)?
  • Only a "new DOMXpath($doc);" is allways secure? need to reload $doc also?

推荐答案

DOMXpath 类(代替 您的另一个问题) 在构造函数中使用对给定 DOMDocument 对象的引用.DOMXpath 根据给定的 DOMDocument 创建 libxml 上下文对象并将其保存到内部类数据中.除了 libxml 上下文之外,它s 保存对在构造函数参数中给出的原始DOMDocument` 的引用.

The DOMXpath class (instead of XSLTProcessor in your another question) use reference to given DOMDocument object in contructor. DOMXpath create libxml context object based on given DOMDocument and save it to internal class data. Besides libxml context its saves references to originalDOMDocument` given in contructor arguments.

这意味着:

来自 ThomasWeinert 的部分示例答案:

Part of sample from ThomasWeinert answer:

var_dump($xpath->document === $dom); // bool(true)  
$dom->loadXml($xml);    
var_dump($xpath->document === $dom); // bool(false)

在加载后给出 false 因为 $dom 已经持有指向新的 libxml 数据的指针但 DOMXpath 持有 libxml$dom 加载前的上下文和加载后指向真实文档的指针.

gives false after load becouse of $dom already holds pointer to new libxml data but DOMXpath holds libxml context for $dom before load and pointer to real document after load.

现在关于query作品

Now about query works

如果它应该返回 XPATH_NODESET(如你的情况),它会创建一个节点副本 - 一个节点一个节点地迭代抛出检测到的节点集(\ext\dom\xpath.c 来自 468 行).复制但以原始文档节点为父节点.这意味着您可以修改结果,但这使您的 XPath 和 DOMDocument 连接消失了.

If it should return XPATH_NODESET (as in your case) its make a node copy - node by node iterating throw detected node set(\ext\dom\xpath.c from 468 line). Copy but with original document node as parent. Its means that you can modify result but this gone away you XPath and DOMDocument connection.

XPath 结果提供了一个知道其来源的 parentNode 成员:

XPath results provide a parentNode memeber that knows their origin:

  • 对于属性值,parentNode 返回携带它们的元素.一个例子是//foo/@attribute,其中父元素是一个 foo 元素.
  • 对于 text() 函数(如在//text() 中),它返回包含返回的文本或尾部的元素.
  • 注意 parentNode 可能并不总是返回一个元素.例如,XPath 函数 string() 和 concat() 将构造没有原点的字符串.对于它们,parentNode 将返回 None.

所以,

  1. 没有任何理由缓存 XPath.除了 xmlXPathNewContext(只分配轻量级的 internal struct).
  2. 每次修改DOMDocument(removeChild、replaceChild 等)时,您都应该重新创建XPath.
  3. 我们不能使用 normalizeDocument 之类的东西来刷新 DOM",因为它会改变内部文档结构并使 Xpath 构造函数中创建的 xmlXPathNewContext 无效.
  4. 只有new DOMXpath($doc);"总是安全的吗?是的,如果您不在 Xpath 使用之间更改 $doc.还需要重新加载 $doc - 不,因为它使之前创建的 xmlXPathNewContext 失效.
  1. There is no any reasons to cache XPath. It do not anything besides xmlXPathNewContext (just allocate lightweight internal struct).
  2. Each time your modify your DOMDocument (removeChild, replaceChild, etc.) your should recreate XPath.
  3. We can not use something like normalizeDocument to "refresh DOM" because of it change internal document structure and invalidate xmlXPathNewContext created in Xpath constructor.
  4. Only "new DOMXpath($doc);" is allways secure? Yes, if you do not change $doc between Xpath usage. Need to reload $doc also - no, because of it invalidated previously created xmlXPathNewContext.

这篇关于在DomDocument中,复用DOMXpath,是否稳定?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-20 23:33