PHP DOMDocument在克隆/返回时更改节点类实例?

时间:2012-12-01 14:04:10

标签: php xml dom

我设法使用PHP DOM实现来创建包含DOMElement子类的自定义文档树,但我发现了一些非常奇怪的东西:克隆或返回DOMDocument似乎改变了子节点类。

基本示例

class Section extends DOMElement
{
  public function __construct($name, $value = null, $uri = null)
  {
    parent::__construct($name, $value, $uri);
  }
}

class Paragraph extends DOMElement
{
  public function __construct($name, $value = null, $uri = null)
  {
    parent::__construct($name, $value, $uri);
  }
}

function display_doc($label, DOMDocument $doc)
{
  $endl = (PHP_SAPI == "cli") ? "\n" : "<br />";
  $pad  = (PHP_SAPI == "cli") ? "\t" : "  ";
  echo ($label . $endl);

  $root = $doc->documentElement;
  echo ($pad . "root " . get_class($root) . $endl);
  echo ($pad . "first child " . get_class($root->firstChild) . $endl);
}

function test_dom($name, DOMDocument &$instance = null)
{
  $doc = ($instance) ? $instance : new DOMDocument("1.0", "utf-8");
  $root = $doc->appendChild($doc->createElement("root"));
  $section = new Section("section");

  $root->appendChild($section);
  $paragraph = new Paragraph("para");
  $section->appendChild($paragraph);

  $clone = clone $doc;

  display_doc($name . " - Inside function", $doc);
  display_doc($name . " - Inside function (clone)", $clone);

  return $doc;
}

$doc = test_dom("Using new instance");
display_doc("Returned doc in global scope", $doc);

$doc2 = new DOMDocument("1.0", "utf-8");
test_dom("Using global scope instance", $doc2);
display_doc("Modified doc in global scope", $doc2);

将输出

Using new instance - Inside function
    root DOMElement
    first child Section
Using new instance - Inside function (clone)
    root DOMElement
    first child DOMElement
Returned doc in global scope
    root DOMElement
    first child DOMElement
Using global scope instance - Inside function
    root DOMElement
    first child Section
Using global scope instance - Inside function (clone)
    root DOMElement
    first child DOMElement
Modified doc in global scope
    root DOMElement
    first child DOMElement

克隆或返回文档时,第一个孩子的班级从Section更改为简单DOMElement

  • 我的PHP版本是5.3.10但在5.4
  • 下会出现相同的行为
  • 使用DOMDocument :: registerNodeClass将由注册的节点类转换DOMElement,但我有多个DOMElement的子类

我的问题不是找到解决方法或不同的解决方案,但我想了解这里发生了什么以及子节点转换的机制。

编辑:我发现了与此问题相关的错误报告(2年):http://www.mail-archive.com/php-bugs@lists.php.net/msg134710.html。 建议的解决方法运行良好但不清楚它是否是一个真正的错误或无效使用DOM API

1 个答案:

答案 0 :(得分:1)

当你使用new Paragraphnew Section时,你需要将它们存储在一个单独的数组中,以便将它们保存在内存中,这样DOMDocument不会只使用它的默认类。 / p>

错误报告是准确的,我认为PHP中DOM的整个实现存在缺陷。

将对象的副本保存在别处是内存密集型的,就像使用DOM一样。由于存在许多缺陷,我正在为个人努力工作而努力工作,所以你不是唯一一个:)