Skip to content

Dom\HTMLDocument::querySelectorAll() returns duplicates for selector lists #25210

Closed as not planned

Description

@phcorp

Description

Dom\HTMLDocument::querySelectorAll() returns an element once per selector of a selector list it matches. The DOM standard says the result holds each element once, in tree order ("scope-match a selectors string" returns a set).

<?php
$d = Dom\HTMLDocument::createFromString('<!doctype html><ul><li>a<ol><li id="x">b</li></ol></li></ul>');

$ids = [];
foreach ($d->querySelectorAll('ul li, ol li') as $li) {
    $ids[] = $li->id ?: $li->textContent;
}
var_dump($ids);

Resulted in this output:

array(3) { [0]=> string(2) "ab" [1]=> string(1) "x" [2]=> string(1) "x" }

But I expected this output instead:

array(2) { [0]=> string(2) "ab" [1]=> string(1) "x" }

Element::querySelectorAll() behaves the same. Browsers return 2 elements.

PHP Version

PHP 8.5.12

Operating System

macOS

Activity

  1. phcorp commented on Nov 5, 2026

    @phcorp
    Author

    This is a duplicate of GH-24260, which was fixed in d1fdbba. That commit makes dom_parent_node_query_selector_all() pass LXB_SELECTORS_OPT_MATCH_FIRST instead of LXB_SELECTORS_OPT_DEFAULT, so lexbor stops after the first selector in the list that matches a node.

    The fix is on PHP-8.4, PHP-8.5 and master, and it is in php-8.5.13RC1. PHP 8.5.12 predates it. Closing as a duplicate.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions