在DomDocument中,复用DOMXpath,是否稳定?

2023-12-04

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

何时以及谁可以稳定/安全地“重用 DOMXpath 准备过程的部分内容”?

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

   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??
   }

目前的问题类似于另一个关于XSLT处理器的重用。 在这两个问题中,问题都可以推广到使用 LibXML2 作为 DomDocument 实现的任何语言或框架。

还有另一个相关问题:如何“刷新”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等(示例),

   $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! !!

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

  • When(哪些 DOMDocument 方法影响 XPath?)
  • Why我们不能使用类似的东西规范化文档“刷新 DOM”(存在吗?)?
  • 只有“new DOMXpath($doc);”总是安全的吗?还需要重新加载 $doc 吗?

DOMXpath 受 DOMDocument 上的 load*() 方法的影响。加载新的 xml 或 html 后,需要重新创建 DOMXpath 实例:

$xml = '<xml/>';    
$dom = new DOMDocument();
$dom->loadXml($xml);
$xpath = new DOMXpath($dom);

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

$dom->loadXml($xml);

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

在 DOMXpath_reuser() 中,您存储静态变量并根据文件名重新创建 xpath。如果您想重用 Xpath 对象,建议扩展 DOMDocument。这样你只需要传递 $dom 变量。它可以与存储的 xml 文件以及 xml 字符串或您正在创建的文档一起使用。

以下类使用 xpath() 方法扩展 DOMDocument,该方法始终为其返回有效的 DOMXpath 实例。它也存储和注册名称空间:

class MyDOMDocument
  extends DOMDocument {

  private $_xpath = NULL;
  private $_namespaces = array();

  public function xpath() {
    // if the xpath instance is missing or not attached to the document
    if (is_null($this->_xpath) || $this->_xpath->document != $this) {
      // create a new one
      $this->_xpath = new DOMXpath($this);
      // and register the namespaces for it
      foreach ($this->_namespaces as $prefix => $namespace) {
        $this->_xpath->registerNamespace($prefix, $namespace);
      }
    }
    return $this->_xpath;
  }

  public function registerNamespaces(array $namespaces) {
    $this->_namespaces = array_merge($this->_namespaces, $namespaces);
    if (isset($this->_xpath)) {
      foreach ($namespaces as $prefix => $namespace) {
        $this->_xpath->registerNamespace($prefix, $namespace);
      }
    }
  }
}

$xml = <<<'ATOM'
  <feed xmlns="http://www.w3.org/2005/Atom">
    <title>Test</title>
  </feed>
ATOM;


$dom = new MyDOMDocument();
$dom->registerNamespaces(
  array(
    'atom' => 'http://www.w3.org/2005/Atom'
  )
);
$dom->loadXml($xml);
// created, first access
var_dump($dom->xpath()->evaluate('string(/atom:feed/atom:title)', NULL, FALSE));
$dom->loadXml($xml);
// recreated, connection was lost
var_dump($dom->xpath()->evaluate('string(/atom:feed/atom:title)', NULL, FALSE));
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在DomDocument中,复用DOMXpath,是否稳定? 的相关文章

  • ORDER BY 字段内的 MySQL 子查询。 (没有内连接)

    有很多与此相关的问题 但都具有使用内部联接的相同答案 这 我认为 在这里是不可能的 如果我错了请告诉我 我现在正在做的是调用两个不同的 mysql 查询来获取结果 它工作完美 db gt query SELECT FROM meta WHE
  • jquery:选择xpath或将xpath转换为css?

    我需要基于 xpath 选择 或者将 xpath 转换为 css 有插件或者内置功能吗 ex html body div a 4 each 并非所有 xpath 表达式都可以转换为类似 CSS 的选择器 或者不能有效地工作 您可以使用 eq
  • openssl_pkey_get_details($res) 不返回公共指数

    我在用着这个例子 https stackoverflow com a 12575951 2016196使用 php 生成的密钥进行 javascript 加密openssl图书馆 但是 details openssl pkey get de
  • PHP MySQL 使用选项/选择 HTML 表单标签进行多重搜索查询

    我正在尝试使用两个搜索字段设置基本的 MySQL LIKE 搜索 我不想拥有它 所以它有多个可选搜索字段 例如if isset POST city isset POST name 我不知道如何用 HTML 来做到这一点
  • 如何在响应ajax codeigniter后停止执行其他控制器

    我想知道如何在响应输出 json 数据后停止执行函数和涉及的其他控制器 就我这里的情况而言 我只是打电话test 函数于dashboard控制器 In dashboard构造函数将执行MY Login library In MY Login
  • Woocommerce 让产品显示在存档页面中

    我正在尝试让所有产品显示在我商店的存档页面中 我想知道他们的id我正在使用我的一个钩子 它在 wp head 上运行并检查 if is product category 我想以某种方式访问 产品的查询并获取它们的 ID if is prod
  • 扩展蓝图类?

    我想覆盖timestamps 函数中发现Blueprint班级 我怎样才能做到这一点 e g public function up Schema create users function Blueprint table table gt
  • 使用 preg_replace 仅替换第一个匹配项

    我有一个结构类似于以下的字符串 aba aaa cba sbd dga gad aaa cbz 该字符串每次都可能有点不同 因为它来自外部源 我只想替换第一次出现的 aaa 但其他人则不然 是否可以 可选的第四个参数预替换 http php
  • 从 .phar 存档中提取文件

    对于 Phar 文件 我完全错过了一些东西 我正在安装一个需要 phpunit pdepend 和其他依赖项的项目 我将它们作为 phar 文件获取 但是 我无法使用命令行工具 php 命令 从中提取文件 我用谷歌搜索了这个问题 但没有发现
  • PHP 在输入流中使用 fwrite 和 fread

    我正在寻找将 PHP 输入流的内容写入磁盘的最有效方法 而不使用授予 PHP 脚本的大量内存 例如 如果可以上传的最大文件大小为 1 GB 但 PHP 只有 32 MB 内存 define MAX FILE LEN 1073741824 1
  • 在 PHP 中撤销 Google 访问令牌

    正如标题所示 我想以编程方式撤销授予的访问令牌 即在 PHP 中 我发现这个他们的网站 https developers google com identity protocols OAuth2WebServer tokenrevoke 但
  • PHP preg_filter 返回意外的长值

    尝试在 Woocommerce 中删除标签并过滤值 但无法以正确的格式获取它 有东西有腥味 我正在使用WC gt cart gt get cart subtotal 来检索该值 在此示例中 我的值是 2 429kr 原始返回值是 span
  • Woocommerce 结账自定义选择字段

    我有以下功能 将选择列表添加到 woo commerce 结账表单中 woocommerce form field airport pickup array type gt select class gt array airport pic
  • php 错误 fopen(): 文件名不能为空

    发送带有附件代码的电子邮件工作正常 最近我们已将文件传输到另一个托管服务器 idk 发生了什么 它显示以下错误 警告 fopen 第 106 行 home hugerecruitmetnt public html validatecva p
  • CURL 中的 data-urlencode 是什么意思?

    我搜索了很多个小时试图弄清楚 php curl 中的 data urlencode 是什么 我尝试过这个 但我认为这是不对的 xmlpost object1 file https www lob com goblue pdf 在文档中是 d
  • Laravel 中只向登录用户显示按钮

    如果我以 John 身份登录 如何才能只显示 John 的红色按钮而不显示 Susan 的红色按钮 测试系统环境 Win10 Laravel5 4 Mysql5 7 19 table class table table responsive
  • 无效的选择器:使用 Selenium 时不允许出现复合类名错误

    我正在尝试通过 Web Whatsapp 打印聊天中的一条消息 我可以通过 控制台 选项卡中的 Javascript 来完成此操作 我就是这样做的 recived msg document getElementsByClassName XE
  • php,统计字符并删除超过140个字符的内容

    我需要一个 PHP 函数来计算短语的字符数 如果短语长度超过 140 个字符 则此函数应删除所有其他字符并在短语末尾添加三个点 例如我们有 message I am what I am and you are what you are et
  • ini_set 'session.gc_maxlifetime' 为 1 天

    If I do ini set session gc maxlifetime 86400 这是否意味着用户可以将浏览器留在同一页面 非活动状态 最多 1 天 而不必担心会话被垃圾收集并被注销 如果服务器配置不支持此功能会发生什么 它会给我一
  • 简单的 PHP 表单:电子邮件附件(代码 Golf)

    想象一下 一个用户想要在其网站上放置一个表单 该表单将允许网站访问者上传一个文件和一条简单的消息 该消息将立即通过电子邮件发送 即 该文件未存储在服务器上 或者如果该文件存储在服务器上 仅暂时 作为文件附件 并在邮件正文中添加注释 查看更多

随机推荐