Seeing this answer, she for many years without a conclusion, finally an update! Now I am faced with a similar problem, and it turned out that DOMXPath just a memory leak, and you cannot control it. I did not search if this was reported on bug.php.net (this may be useful for editing later).
The “working” solutions that I found in this problem are workarounds. The main idea was to replace the DOMNodeList Traversable returned by DOMXPath::query() with another containing the same nodes.
The most suitable approach is DOMXPathElementsIterator , which allows you to query for the specific xpath expression that you have in your question, without leak memory:
$nodes = new DOMXPathElementsIterator($this->dom, "//span[@class='ckass']"); foreach ($nodes as $span) { ... }
This class is now part of the Iterator-Garden development version and $nodes is an iterator over all <span> DOMElements.
The disadvantage of this workaround is that the result of xpath is limited to the result of SimpleXMLElement::xpath() (this is different from DOMXPath::query() ) because it is used to prevent memory leaks.
Another alternative is to use the DOMNodeListIterator over the DOMNodeList as the one returned by DOMDocument::getElementsByTagname() . However, these iterations are slow.
Hope this is helpful, even the question was really old. It helped me in a similar situation.
Calling garbage collector cleaning circles makes sense if objects are no longer referenced (used).
For example, if you create a new DOMXPath object for the same DOMDocument again and again (remember that it is connected to a DOMDocument that still exists), it looks like your memory is “leak”. You just use more and more memory.
Instead, you can simply reuse an existing DOMXPath object while reusing the DOMDocument object all the time. Try:
//Loaded outside of loop $this->dom = new DOMDocument(); $xpath = new DOMXPath($this->dom); //Inside Loop $this->dom->loadHTML($output); $nodes = $xpath->query("//span[@class='ckass']");