Description
Please consider the following example code, showing the issue:
$dom = new \DOMDocument();
$dom->loadXML('<html><form><div><input type="submit"/></div></form></html>');
$crawler = new \Symfony\Component\DomCrawler\Crawler($dom, 'http://www.example.org/');
// This one works fine:
$form = $crawler->filter('div input')->form();
// This one breaks: ("The selected node does not have a form ancestor")
$form = $crawler->filter('div')->filter('input')->form();
Because filterXPath()
(which is used by filter()
) creates a new \DOMDocument with only the current nodes on it, successive calls to filterXPath() will lose track of the rest of the original DOM. After the first filterXPath()
, this is not a problem yet, since the filtered nodes can still 'reach' the rest of the DOM, since it was added to the new \DOMDocument. However, the second filterXPath()
will create a new \DOMDocument with only the (previously) filtered nodes on it, effectively leaving the rest of the original DOM (including the parent form in this case) unreachable!
I ran into this issue when using fabpot/Goutte to first filter on table rows which each had a submit button, which I needed to 'click'. It looked something like this:
$crawler->filter('tr')->each(function ($row) {
$someValue = $row->filter('td.somecolumn')->text();
// This breaks: ("The selected node does not have a form ancestor")
$form = $row->filter('input')->form();
});