8000 [DomCrawler] Add support for XPath expression evaluation · symfony/symfony@a6a5cfe · GitHub
[go: up one dir, main page]

Skip to content

Commit a6a5cfe

Browse files
committed
[DomCrawler] Add support for XPath expression evaluation
1 parent 695549f commit a6a5cfe

File tree

2 files changed

+64
-0
lines changed

2 files changed

+64
-0
lines changed

src/Symfony/Component/DomCrawler/Crawler.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,33 @@ public function html()
592592
return $html;
593593
}
594594

595+
/**
596+
* Evaluates an XPath expression.
597+
*
598+
* Since an XPath expression might evaluate to either a simple type or a \DOMDoneList,
599+
* this method will return either an array of simple types or a new Crawler instance.
600+
*
601+
* @param string $xpath An XPath expression
602+
*
603+
* @return array|Crawler An array of evaluation results or a new Crawler instance
604+
*/
605+
public function evaluate($xpath)
606+
{
607+
$data = array();
608+
$prefixes = $this->findNamespacePrefixes($xpath);
609+
610+
foreach ($this->nodes as $node) {
611+
$domxpath = $this->createDOMXPath($node->ownerDocument, $prefixes);
612+
$data[] = $domxpath->evaluate($xpath, $node);
613+
}
614+
615+
if (isset($data[0]) && $data[0] instanceof \DOMNodeList) {
616+
return $this->createSubCrawler($data);
617+
}
618+
619+
return $data;
620+
}
621+
595622
/**
596623
* Extracts information from the list of nodes.
597624
*

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

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1061,6 +1061,43 @@ public function testCountOfNestedElements()
10611061
$this->assertCount(1, $crawler->filter('li:contains("List item 1")'));
10621062
}
10631063

1064+
public function testEvaluateReturnsTypedResultOfXPathExpressionOnADocumentSubset()
1065+
{
1066+
$crawler = $this->createTestCrawler();
1067+
1068+
$result = $crawler->filterXPath('//form/input')->evaluate('substring-before(@name, "Name")');
1069+
1070+
$this->assertSame(array('Text', 'Foo', 'Bar'), $result);
1071+
}
1072+
1073+
public function testEvaluateReturnsTypedResultOfNamespacedXPathExpressionOnADocumentSubset()
1074+
{
1075+
$crawler = $this->createTestXmlCrawler();
1076+
1077+
$result = $crawler->filterXPath('//yt:accessControl/@action')->evaluate('string(.)');
1078+
1079+
$this->assertSame(array('comment', 'videoRespond'), $result);
1080+
}
1081+
1082+
public function testEvaluateReturnsTypedResultOfNamespacedXPathExpression()
1083+
{
1084+
$crawler = $this->createTestXmlCrawler();
1085+
$crawler->registerNamespace('youtube', 'http://gdata.youtube.com/schemas/2007');
1086+
1087+
$result = $crawler->evaluate('string(//youtube:accessControl/@action)');
1088+
1089+
$this->assertSame(array('comment'), $result);
1090+
}
1091+
1092+
public function testEvaluateReturnsACrawlerIfXPathExpressionEvaluatesToANode()
1093+
{
1094+
$crawler = $this->createTestCrawler()->evaluate('//form/input[1]');
1095+
1096+
$this->assertInstanceOf(Crawler::class, $crawler);
1097+
$this->assertCount(1, $crawler);
1098+
$this->assertSame('input', $crawler->first()->nodeName());
1099+
}
1100+
10641101
public function createTestCrawler($uri = null)
10651102
{
10661103
$dom = new \DOMDocument();

0 commit comments

Comments
 (0)
0