symfony/css-selector
Symfony CssSelector converts CSS selectors into XPath expressions, making it easy to query DOM/XML documents with familiar CSS syntax. Part of the Symfony Components ecosystem, with full docs and issue tracking in the main Symfony repository.
Strengths:
symfony/css-selector) aligns perfectly with Laravel’s ecosystem, particularly for DOM manipulation, scraping, and testing. The :is()/:where() combinators directly address Laravel’s pain points in dynamic class handling (e.g., Blade, scraping pipelines).:has(), :is() nesting).Risks:
v8.1.0-BETA3 introduces fixes but remains in beta. Potential edge cases in combinator parsing (e.g., nested :is() with parent selectors) may surface in production.div:is(.a:is(.b, .c), .d)) could degrade performance or introduce bugs if not tested rigorously.spatie/laravel-web-scraper, DOMDocument, Pest/PHPUnit). Integration requires minimal changes—primarily replacing custom XPath logic with standardized combinators.spatie/laravel-web-scraper with :is()-based queries.SimpleXML/DOMDocument.v8.1.0-BETA3 suggest stability improvements, but production use should wait for v8.1.0 GA.league/css-to-xpath for unsupported selectors during migration.Selector Coverage:
symfony/css-selector’s :is()/:where() support?div > :is(p, span) work as expected in nested contexts?Performance Impact:
league/css-to-xpath for regression testing.Testing Strategy:
:is() selectors in Pest/PHPUnit against real-world DOM snapshots.Rollback Plan:
v8.1.0 introduces regressions post-GA?league/css-to-xpath handle all edge cases during migration?Long-Term Maintenance:
:has())?Primary Use Cases in Laravel (Updated for v8.1.0-BETA3):
Web Scraping:
v8.1.0-BETA3 address combinator edge cases (e.g., div:is(.user--active, .user--premium) > span).$scraper->scrape('https://example.com')->css('div:is(.product, .sale)')->each(...);
Testing Frameworks:
:is() with parent combinators).assertSelectorExists($dom, 'div:is(.desktop, .mobile):has(> button)');
DOM/XML Processing:
<item :is="active, featured">) in SimpleXML.$xpath = CssSelector::toXPath('item:is(active, featured)');
Blade Templating:
@xpath('div:is(.desktop, .mobile):has(> .nav)')).@php $xpath = CssSelector::toXPath('div:is(.header, .footer) > *'); @endphp
@xpath($xpath)
Data Extraction Utilities:
DOMDocument).Secondary Use Cases (Updated):
div:is(.variant-a, .variant-b):has(.cta)).[aria-label]:is(:focus, :hover)).:is()/:where() for maintainability.Phase 1: Assessment (1 week)
:is()).git grep for CssSelector::toXPath and custom XPath logic.div > :is(p, span)) or deep nesting.v8.1.0-BETA3 against known flaky selectors.Phase 2: Proof of Concept (2 weeks)
v8.1.0-BETA3 in a controlled module (e.g., scraping tool).:is() + :has()).composer require symfony/css-selector:8.1.0-BETA3
div:is(.a:is(.b, .c), .d).ul > li:is(.item, .highlight).league/css-to-xpath.Phase 3: Incremental Rollout (4–6 weeks)
trait CssSelectorHelper {
public static function toXPath(string $selector): string {
return CssSelector::toXPath($selector);
}
}
league/css-to-xpath for unsupported combinators.v8.1.0-BETA3 limitations.Phase 4: Optimization (2 weeks)
#64250).league/css-to-xpath post-GA.How can I help you explore Laravel packages today?