Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

fix axes handling in Crawler::filterXPath()

Due to some limitations in the relativize() method, it was not
possible to use XPath axes other than descendant or descendant-or-self
in the filterXPath() method of the Crawler class. This commit adds
support for the ancestor, ancestor-or-self, attribute, child,
following, following-sibling, parent, preceding, preceding-sibling and
self axes.
  • Loading branch information...
commit 8dc322be34f89a325dda276cb698d9f5c48cdcae 1 parent cd005e6
@xabbuh xabbuh authored
View
2  src/Symfony/Component/DomCrawler/Crawler.php
@@ -854,7 +854,7 @@ private function relativize($xpath)
$expression = $nonMatchingExpression;
} elseif (0 === strpos($expression, 'descendant::')) {
$expression = 'descendant-or-self::' . substr($expression, strlen('descendant::'));
- } elseif (0 !== strpos($expression, 'descendant-or-self::')) {
+ } elseif (!preg_match('/^(ancestor|ancestor-or-self|attribute|child|descendant-or-self|following|following-sibling|parent|preceding|preceding-sibling|self)::/', $expression)) {
$expression = 'self::' .$expression;
}
$expressions[] = $parenthesis.$expression;
View
68 src/Symfony/Component/DomCrawler/Tests/CrawlerTest.php
@@ -411,6 +411,74 @@ public function testFilterXPath()
$this->assertCount(3, $crawler->filterXPath('//body')->filterXPath('//button')->parents(), '->filterXpath() preserves parents when chained');
}
+ public function testFilterXPathWithAncestorAxis()
+ {
+ $crawler = $this->createTestCrawler()->filterXPath('//form');
+
+ $this->assertCount(2, $crawler->filterXPath('ancestor::*'));
+ }
+
+ public function testFilterXPathWithAncestorOrSelfAxis()
+ {
+ $crawler = $this->createTestCrawler()->filterXPath('//form');
+
+ $this->assertCount(3, $crawler->filterXPath('ancestor-or-self::*'));
+ }
+
+ public function testFilterXPathWithAttributeAxis()
+ {
+ $crawler = $this->createTestCrawler()->filterXPath('//form');
+
+ $this->assertCount(2, $crawler->filterXPath('attribute::*'));
+ }
+
+ public function testFilterXPathWithChildAxis()
+ {
+ $crawler = $this->createTestCrawler()->filterXPath('//body');
+
+ $this->assertCount(2, $crawler->filterXPath('child::input'));
+ }
+
+ public function testFilterXPathWithFollowingAxis()
+ {
+ $crawler = $this->createTestCrawler()->filterXPath('//a');
+
+ $this->assertCount(3, $crawler->filterXPath('following::div'));
+ }
+
+ public function testFilterXPathWithFollowingSiblingAxis()
+ {
+ $crawler = $this->createTestCrawler()->filterXPath('//a');
+
+ $this->assertCount(2, $crawler->filterXPath('following-sibling::div'));
+ }
+
+ public function testFilterXPathWithParentAxis()
+ {
+ $crawler = $this->createTestCrawler()->filterXPath('//button');
+
+ $this->assertEquals('foo', $crawler->filterXPath('parent::*')->attr('action'));
+ }
+
+ public function testFilterXPathWithPrecedingAxis()
+ {
+ $crawler = $this->createTestCrawler()->filterXPath('//form');
+
+ $this->assertCount(13, $crawler->filterXPath('preceding::*'));
+ }
+
+ public function testFilterXPathWithPrecedingSiblingAxis()
+ {
+ $crawler = $this->createTestCrawler()->filterXPath('//form');
+
+ $this->assertCount(9, $crawler->filterXPath('preceding-sibling::*'));
+ }
+
+ public function testFilterXPathWithSelfAxes()
+ {
+ $this->assertCount(1, $this->createTestCrawler()->filterXPath('self::*'));
+ }
+
/**
* @covers Symfony\Component\DomCrawler\Crawler::filter
*/
Please sign in to comment.
Something went wrong with that request. Please try again.