Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f634afd

Browse files
Einenlumnicolas-grekas
authored andcommitted
[DomCrawler] Add a way to filter direct children
1 parent f0168e3 commit f634afd

File tree

2 files changed

+57
-6
lines changed

2 files changed

+57
-6
lines changed

src/Symfony/Component/DomCrawler/Crawler.php

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -501,16 +501,28 @@ public function parents()
501501
/**
502502
* Returns the children nodes of the current selection.
503503
*
504+
* @param string|null $selector An optional CSS selector to filter children
505+
*
504506
* @return self
505507
*
506508
* @throws \InvalidArgumentException When current node is empty
509+
* @throws \RuntimeException If the CssSelector Component is not available and $selector is provided
507510
*/
508-
public function children()
511+
public function children(/* string $selector = null */)
509512
{
513+
$selector = 0 < \func_num_args() ? func_get_arg(0) : null;
514+
510515
if (!$this->nodes) {
511516
throw new \InvalidArgumentException('The current node list is empty.');
512517
}
513518

519+
if (null !== $selector) {
520+
$converter = $this->createCssSelectorConverter();
521+
$xpath = $converter->toXPath($selector, 'child::');
522+
523+
return $this->filterRelativeXPath($xpath);
524+
}
525+
514526
$node = $this->getNode(0)->firstChild;
515527

516528
return $this->createSubCrawler($node ? $this->sibling($node) : array());
@@ -691,11 +703,7 @@ public function filterXPath($xpath)
691703
*/
692704
public function filter($selector)
693705
{
694-
if (!class_exists(CssSelectorConverter::class)) {
695-
throw new \RuntimeException('To filter with a CSS selector, install the CssSelector component ("composer require symfony/css-selector"). Or use filterXpath instead.');
696-
}
697-
698-
$converter = new CssSelectorConverter($this->isHtml);
706+
$converter = $this->createCssSelectorConverter();
699707

700708
// The CssSelector already prefixes the selector with descendant-or-self::
701709
return $this->filterRelativeXPath($converter->toXPath($selector));
@@ -1148,4 +1156,16 @@ private function createSubCrawler($nodes)
11481156

11491157
return $crawler;
11501158
}
1159+
1160+
/**
1161+
* @throws \RuntimeException If the CssSelector Component is not available
1162+
*/
1163+
private function createCssSelectorConverter(): CssSelectorConverter
1164+
{
1165+
if (!class_exists(CssSelectorConverter::class)) {
1166+
throw new \RuntimeException('To filter with a CSS selector, install the CssSelector component ("composer require symfony/css-selector"). Or use filterXpath instead.');
1167+
}
1168+
1169+
return new CssSelectorConverter($this->isHtml);
1170+
}
11511171
}

src/Symfony/Component/DomCrawler/Tests/CrawlerTest.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,6 +1004,37 @@ public function testChildren()
10041004
}
10051005
}
10061006

1007+
public function testFilteredChildren()
1008+
{
1009+
$html = <<<'HTML'
1010+
<!DOCTYPE html>
1011+
<html lang="en">
1012+
<body>
1013+
<div id="foo">
1014+
<div class="lorem">
1015+
<p class="lorem"></p>
1016+
</div>
1017+
<div class="lorem">
1018+
<span class="lorem"></span>
1019+
</div>
1020+
<span class="ipsum"></span>
1021+
</div>
1022+
</body>
1023+
</html>
1024+
HTML;
1025+
1026+
$crawler = new Crawler($html);
1027+
$foo = $crawler->filter('#foo');
1028+
1029+
$this->assertEquals(3, $foo->children()->count());
1030+
$this->assertEquals(2, $foo->children('.lorem')->count());
1031+
$this->assertEquals(2, $foo->children('div')->count());
1032+
$this->assertEquals(2, $foo->children('div.lorem')->count());
1033+
$this->assertEquals(1, $foo->children('span')->count());
1034+
$this->assertEquals(1, $foo->children('span.ipsum')->count());
1035+
$this->assertEquals(1, $foo->children('.ipsum')->count());
1036+
}
1037+
10071038
public function testParents()
10081039
{
10091040
$crawler = $this->createTestCrawler()->filterXPath('//li[1]');

0 commit comments

Comments
 (0)