问题描述
我正在使用下面的功能,但不确定它是否始终稳定/安全... 是吗?
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
但是,如果您执行removeChild
、replaceChild
等操作(示例),
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 original
DOMDocument` 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.
所以,
- 没有任何理由缓存
XPath
.除了xmlXPathNewContext
(只分配轻量级的 internal struct). - 每次修改
DOMDocument
(removeChild、replaceChild 等)时,您都应该重新创建XPath
. - 我们不能使用 normalizeDocument 之类的东西来刷新 DOM",因为它会改变内部文档结构并使
Xpath
构造函数中创建的xmlXPathNewContext
无效. - 只有new DOMXpath($doc);"总是安全的吗?是的,如果您不在
Xpath
使用之间更改 $doc.还需要重新加载 $doc - 不,因为它使之前创建的xmlXPathNewContext
失效.
- There is no any reasons to cache
XPath
. It do not anything besidesxmlXPathNewContext
(just allocate lightweight internal struct). - Each time your modify your
DOMDocument
(removeChild, replaceChild, etc.) your should recreateXPath
. - We can not use something like normalizeDocument to "refresh DOM" because of it change internal document structure and invalidate
xmlXPathNewContext
created inXpath
constructor. - 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 createdxmlXPathNewContext
.
这篇关于在DomDocument中,复用DOMXpath,是否稳定?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!