You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
remove() and replaceAll() still match the nodes in hand, unlike find() #126
Once #73 lands, find() searches descendants only, as jQuery's .find() does. remove($selector) and replaceAll($selector) still go through the legacy engine, QueryPath\CSS\QueryPathEventHandler, which counts the nodes in the match set as candidates for their own selector. So the two engines disagree about which nodes a selector reaches:
$xml = '<?xml version="1.0"?><root><p><i>a</i><b>x</b></p><p><i>b</i></p><i>c</i></root>';
qp($xml, 'p')->remove('p')->count(); // 2: both <p> themselvesqp($xml, 'p')->detach('p')->count(); // 0: no <p> below a <p>qp($xml, 'p')->remove('*')->count(); // 5: the two <p> plus their three childrenqp($xml, 'p')->detach('*')->count(); // 3: the three children
detach($selector) was fixed in #108 (issue #76) to detach "the matches of $selector, as remove($selector) does". With #73 that only holds for selectors that cannot match the nodes in hand.
Cause
Every matcher in QueryPathEventHandler (element(), elementID(), elementClass(), anyElement(), elementNS(), anyElementInNS(), attribute(), …) iterates candidateList(), which includes each node in the match set as well as its descendants. anyElement() even says // Add self.
Options
Make candidateList() descendants-only, with the same document-element exception DOMTraverser::isDocumentElement() uses in Make find() search descendants only, as jQuery does #73, so remove()/replaceAll() agree with find().
Activity
Pin detach($selector) to find()'s descendant-only matching
Pin detach($selector) to find()'s descendant-only matching
Pin detach($selector) to find()'s descendant-only matching
Pin detach($selector) to find()'s descendant-only matching
Make find() search descendants only, as jQuery does (#73)