php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #28473 DOM object custom variables get lost
Submitted: 2004-05-21 14:41 UTC Modified: 2004-05-27 11:40 UTC
From: bart at mediawave dot nl Assigned:
Status: Not a bug Package: DOM XML related
PHP Version: 5.0.0RC2 OS: Windows XP
Private report: No CVE-ID: None
 [2004-05-21 14:41 UTC] bart at mediawave dot nl
Description:
------------
Setting custom variables in DOM objects like:

$domNode->customVar = 'myValue';

Are inconsistently lost when working with a dom.

Reproduce code:
---------------
<?php

class myclass {

	function run() {
		$xp = new domxpath($this->dom);

		$widths = $xp->query('//td/@width');
		foreach ($widths as $width) {
			echo $this->name.' 1: width->myVar value:'.$width->myVar.'<br>';
			$width->myVar = '1';
		}		
		$tds = $this->dom->getElementsByTagName('td');
		foreach ($tds as $td) {
			echo $this->name.' 2: td->myVar value:'.$td->myVar.'<br>';
			$td->myVar = '1';
		}
		
		echo '<br>';
		$tds = $this->dom->getElementsByTagName('td');
		foreach ($tds as $td) {
			if ($width = $td->getAttributeNode('width')) {
				echo $this->name.' 3: width->myVar value:'.$width->myVar.'<br>';
				$width->myVar = '2';
			}
			echo $this->name.' 4: td->myVar value:'.$td->myVar.'<br>';
			$td->myVar = '2';
		}
		echo '<br>';
	}
}

$xml = '<root>
		   <tr><td width="40">hello</td><td width="40">world</td></tr>
		   <tr><td>Just one TD</td></tr>
		   <tr><td>TD with <b>mixed</b> <i>content</i></td></tr>
		</root>';

$dom = new DomDocument;
$dom->loadXML($xml);

$firstInstance = new myclass;
$firstInstance->name = 'firstInstance';
$firstInstance->dom = $dom;
$firstInstance->run();
$secondInstance = new myclass;
$secondInstance->name = 'secondInstance';
$secondInstance->dom = $firstInstance->dom;
$secondInstance->run();

?>

Expected result:
----------------
firstInstance 1: width->myVar value:
firstInstance 1: width->myVar value:
firstInstance 2: td->myVar value:
firstInstance 2: td->myVar value:
firstInstance 2: td->myVar value:
firstInstance 2: td->myVar value:

firstInstance 3: width->myVar value:1
firstInstance 4: td->myVar value:1
firstInstance 3: width->myVar value:1
firstInstance 4: td->myVar value:1
firstInstance 4: td->myVar value:1
firstInstance 4: td->myVar value:1

secondInstance 1: width->myVar value:2
secondInstance 1: width->myVar value:2
secondInstance 2: td->myVar value:2
secondInstance 2: td->myVar value:2
secondInstance 2: td->myVar value:2
secondInstance 2: td->myVar value:2

secondInstance 3: width->myVar value:1
secondInstance 4: td->myVar value:1
secondInstance 3: width->myVar value:1
secondInstance 4: td->myVar value:1
secondInstance 4: td->myVar value:1
secondInstance 4: td->myVar value:1

Actual result:
--------------
firstInstance 1: width->myVar value:
firstInstance 1: width->myVar value:
firstInstance 2: td->myVar value:
firstInstance 2: td->myVar value:
firstInstance 2: td->myVar value:
firstInstance 2: td->myVar value:

firstInstance 3: width->myVar value:1
firstInstance 4: td->myVar value:
firstInstance 3: width->myVar value:1
firstInstance 4: td->myVar value:
firstInstance 4: td->myVar value:
firstInstance 4: td->myVar value:

secondInstance 1: width->myVar value:
secondInstance 1: width->myVar value:
secondInstance 2: td->myVar value:
secondInstance 2: td->myVar value:
secondInstance 2: td->myVar value:
secondInstance 2: td->myVar value:

secondInstance 3: width->myVar value:1
secondInstance 4: td->myVar value:
secondInstance 3: width->myVar value:1
secondInstance 4: td->myVar value:
secondInstance 4: td->myVar value:
secondInstance 4: td->myVar value:

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2004-05-24 00:27 UTC] rrichards@php.net
Thank you for taking the time to write to us, but this is not
a bug. Please double-check the documentation available at
http://www.php.net/manual/ and the instructions on how to report
a bug at http://bugs.php.net/how-to-report.php

It all has to do with object lifespans. ->query creates a static set of objects so they live as long as either the returned nodeset exists or the contained objects are referenced (so the width attribute works as you expected).

getElementsByXXX however is a live function (per specs), so does not create any objects unless a node is explicity called for, which means once your object goes out of scope ($td in the foreach loops), the custom properties are gone.
 [2004-05-24 00:54 UTC] bart at mediawave dot nl
So, this means that, when I use the dom functions to find a node. This node actually is sort of a copy in stead of the actual node inside the domDocument?

I'm expecting that all the nodes, elements and attributes are the actual nodes, elements and attributes of the domDocument. Not temporary PHP instances of the actual domDocument objects?
 [2004-05-24 01:56 UTC] rrichards@php.net
You are confusing nodes and objects. The DOM Objects provide the DOM API and are just an interface to the underlying libxml api. So, the objects refer to the actual node, but in reality nodes are not objects per say. The specifics of how it all works gets complicated, but when working on an object you are working on the actual node, but you cant think of it in reverse, as again nodes are not really objects.
 [2004-05-26 16:23 UTC] bart at mediawave dot nl
I'm sure that is the way that libxml is implemented in PHP. However I'm not completely sure if this is the way the W3C designed the DOM to work. Afterall, we're talking about the Document Object Model and not the Document Interface Model. When I look at a domDocument I should think about a tree of objects that have (interface) methods for retrieving and modifying the object tree. I shouldn't be thinking about API interfaces for the underlying libxml implementation.

Furthermore setting custom properties is pretty essential when working with the DOM. When creating software that works with the DOM people will most likely use a bunch of functions, objects or modules that do something with the DOM. With such an approach it's quite common that you will want to set some properties here and there that can then be used by other functions, objects or modules later on. Of course, we could create one gigantic function that does all operations at once. But then we could just as well use Expat.

Also, in the W3C Document Object Model Core documentation at section 1.1.1 it says: 

Likewise, changes to a Node in the tree are reflected in all references to that Node in NodeList and NamedNodeMap  objects.

This doesn't specifically say anything about custom properties. But we are talking about (PHP) Node objects. And changes to those objects should be reflected in all references to that Node. Thus also changing (PHP) object properties.
 [2004-05-27 11:40 UTC] rrichards@php.net
Still bogus. Thats the purpose of get/setUserData introduced in Level 3, but not currently implemented in the DOM extension.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Mar 28 20:01:28 2024 UTC