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.
This commit is contained in:
Christian Flothmann 2014-08-02 10:47:58 +02:00
parent cd005e69ff
commit 8dc322be34
2 changed files with 69 additions and 1 deletions

View File

@ -854,7 +854,7 @@ class Crawler extends \SplObjectStorage
$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 File

@ -411,6 +411,74 @@ EOF
$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
*/