New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement :not() pseudo selector #3256
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I look forward to reviewing this change.
This may be a dirty hack, but it seems to work well.
e8b4e6b
to
4c48b21
Compare
Anything missing here? |
I have not yet reviewed this change. I'm thinking now I'll take a look at inclusion for the next release. |
if(substr($subquery, 0, 4) != '//*[') { | ||
return null; //not supported | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can build out support based on the logic we have for the matches
selector.
$length = strpos($selector, ")", $i) - $p; | ||
$i += $length + 1; | ||
$matchList = trim(mb_substr($selector, $p, $length)); | ||
$subquery = $this->selectorToXpath($matchList, true)['query']; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The subquery produced if $matchList
is a comma-delimited list is broken. I think we need to split the string and parse each selector individually, similar to what's happening for matches
.
$subquery = $this->selectorToXpath($matchList, true)['query']; | ||
if(substr($subquery, 0, 4) != '//*[') { | ||
return null; //not supported | ||
} | ||
$query .= "[not(".substr($subquery, 4, -1).")]"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Recursing into selectorToXpath is problematic since we don't want a full XPath query. That being said the following small tweak seems to work better, though it's still not great. It supports both elements and attributes, but combined selectors are still problematic (e.g., element.class
or .class1.class2
).
$subquery = $this->selectorToXpath($matchList, true)['query']; | |
if(substr($subquery, 0, 4) != '//*[') { | |
return null; //not supported | |
} | |
$query .= "[not(".substr($subquery, 4, -1).")]"; | |
$subqueries = array_map("trim", explode(",", $matchList)); | |
foreach ($subqueries as &$subquery) { | |
if (preg_match("/^\w/", $subquery)) { | |
$subquery = "name() = '$subquery'"; | |
} else { | |
$subquery = substr($this->selectorToXpath($subquery, true)['query'], 4, -1); | |
} | |
} | |
$query .= "[not(" . implode(" or ", $subqueries) . ")]"; |
I'm not sure if this complys wih your coding guidlines and it might not be the way you'd like it be solved, but maybe it's still useful :)