Add a non-static API for the CssSelector component
This commit is contained in:
parent
078f953935
commit
f4563c39ce
@ -1,6 +1,12 @@
|
|||||||
CHANGELOG
|
CHANGELOG
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
2.8.0
|
||||||
|
-----
|
||||||
|
|
||||||
|
* Added the ConverterInterface and the Converter implementation as a non-static API for the component.
|
||||||
|
* Deprecated the `CssSelector` static API of the component.
|
||||||
|
|
||||||
2.1.0
|
2.1.0
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
56
src/Symfony/Component/CssSelector/Converter.php
Normal file
56
src/Symfony/Component/CssSelector/Converter.php
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\CssSelector;
|
||||||
|
|
||||||
|
use Symfony\Component\CssSelector\Parser\Shortcut\ClassParser;
|
||||||
|
use Symfony\Component\CssSelector\Parser\Shortcut\ElementParser;
|
||||||
|
use Symfony\Component\CssSelector\Parser\Shortcut\EmptyStringParser;
|
||||||
|
use Symfony\Component\CssSelector\Parser\Shortcut\HashParser;
|
||||||
|
use Symfony\Component\CssSelector\XPath\Extension\HtmlExtension;
|
||||||
|
use Symfony\Component\CssSelector\XPath\Translator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Christophe Coevoet <stof@notk.org>
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
class Converter implements ConverterInterface
|
||||||
|
{
|
||||||
|
private $translator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool $html Whether HTML support should be enabled. Disable it for XML documents.
|
||||||
|
*/
|
||||||
|
public function __construct($html = true)
|
||||||
|
{
|
||||||
|
$this->translator = new Translator();
|
||||||
|
|
||||||
|
if ($html) {
|
||||||
|
$this->translator->registerExtension(new HtmlExtension($this->translator));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->translator
|
||||||
|
->registerParserShortcut(new EmptyStringParser())
|
||||||
|
->registerParserShortcut(new ElementParser())
|
||||||
|
->registerParserShortcut(new ClassParser())
|
||||||
|
->registerParserShortcut(new HashParser())
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function toXPath($cssExpr, $prefix = 'descendant-or-self::')
|
||||||
|
{
|
||||||
|
return $this->translator->cssToXPath($cssExpr, $prefix);
|
||||||
|
}
|
||||||
|
}
|
75
src/Symfony/Component/CssSelector/ConverterInterface.php
Normal file
75
src/Symfony/Component/CssSelector/ConverterInterface.php
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\CssSelector;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ConverterInterface is the main entry point of the component and can convert CSS
|
||||||
|
* selectors to XPath expressions.
|
||||||
|
*
|
||||||
|
* This component is a port of the Python cssselect library,
|
||||||
|
* which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2007-2012 Ian Bicking and contributors. See AUTHORS
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of Ian Bicking nor the names of its contributors may
|
||||||
|
* be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL IAN BICKING OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* @author Christophe Coevoet <stof@notk.org>
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
interface ConverterInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Translates a CSS expression to its XPath equivalent.
|
||||||
|
*
|
||||||
|
* Optionally, a prefix can be added to the resulting XPath
|
||||||
|
* expression with the $prefix parameter.
|
||||||
|
*
|
||||||
|
* @param string $cssExpr The CSS expression.
|
||||||
|
* @param string $prefix An optional prefix for the XPath expression.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
public function toXPath($cssExpr, $prefix = 'descendant-or-self::');
|
||||||
|
|
||||||
|
}
|
@ -11,12 +11,7 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\CssSelector;
|
namespace Symfony\Component\CssSelector;
|
||||||
|
|
||||||
use Symfony\Component\CssSelector\Parser\Shortcut\ClassParser;
|
@trigger_error('The '.__NAMESPACE__.'\CssSelector class is deprecated since version 2.8 and will be removed in 3.0. Use directly the \Symfony\Component\CssSelector\Converter class instead.', E_USER_DEPRECATED);
|
||||||
use Symfony\Component\CssSelector\Parser\Shortcut\ElementParser;
|
|
||||||
use Symfony\Component\CssSelector\Parser\Shortcut\EmptyStringParser;
|
|
||||||
use Symfony\Component\CssSelector\Parser\Shortcut\HashParser;
|
|
||||||
use Symfony\Component\CssSelector\XPath\Extension\HtmlExtension;
|
|
||||||
use Symfony\Component\CssSelector\XPath\Translator;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CssSelector is the main entry point of the component and can convert CSS
|
* CssSelector is the main entry point of the component and can convert CSS
|
||||||
@ -62,6 +57,8 @@ use Symfony\Component\CssSelector\XPath\Translator;
|
|||||||
*
|
*
|
||||||
* @author Fabien Potencier <fabien@symfony.com>
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
*
|
*
|
||||||
|
* @deprecated as of 2.8, will be removed in 3.0. Use the \Symfony\Component\CssSelector\Converter class instead.
|
||||||
|
*
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
class CssSelector
|
class CssSelector
|
||||||
@ -82,20 +79,9 @@ class CssSelector
|
|||||||
*/
|
*/
|
||||||
public static function toXPath($cssExpr, $prefix = 'descendant-or-self::')
|
public static function toXPath($cssExpr, $prefix = 'descendant-or-self::')
|
||||||
{
|
{
|
||||||
$translator = new Translator();
|
$converter = new Converter(self::$html);
|
||||||
|
|
||||||
if (self::$html) {
|
return $converter->toXPath($cssExpr, $prefix);
|
||||||
$translator->registerExtension(new HtmlExtension($translator));
|
|
||||||
}
|
|
||||||
|
|
||||||
$translator
|
|
||||||
->registerParserShortcut(new EmptyStringParser())
|
|
||||||
->registerParserShortcut(new ElementParser())
|
|
||||||
->registerParserShortcut(new ClassParser())
|
|
||||||
->registerParserShortcut(new HashParser())
|
|
||||||
;
|
|
||||||
|
|
||||||
return $translator->cssToXPath($cssExpr, $prefix);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
36
src/Symfony/Component/CssSelector/Tests/ConverterTest.php
Normal file
36
src/Symfony/Component/CssSelector/Tests/ConverterTest.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\CssSelector\Tests;
|
||||||
|
|
||||||
|
use Symfony\Component\CssSelector\Converter;
|
||||||
|
|
||||||
|
class ConverterTest extends \PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
|
public function testCssToXPath()
|
||||||
|
{
|
||||||
|
$converter = new Converter();
|
||||||
|
|
||||||
|
$this->assertEquals('descendant-or-self::*', $converter->toXPath(''));
|
||||||
|
$this->assertEquals('descendant-or-self::h1', $converter->toXPath('h1'));
|
||||||
|
$this->assertEquals("descendant-or-self::h1[@id = 'foo']", $converter->toXPath('h1#foo'));
|
||||||
|
$this->assertEquals("descendant-or-self::h1[@class and contains(concat(' ', normalize-space(@class), ' '), ' foo ')]", $converter->toXPath('h1.foo'));
|
||||||
|
$this->assertEquals('descendant-or-self::foo:h1', $converter->toXPath('foo|h1'));
|
||||||
|
$this->assertEquals('descendant-or-self::h1', $converter->toXPath('H1'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCssToXPathXml()
|
||||||
|
{
|
||||||
|
$converter = new Converter(false);
|
||||||
|
|
||||||
|
$this->assertEquals('descendant-or-self::H1', $converter->toXPath('H1'));
|
||||||
|
}
|
||||||
|
}
|
@ -13,6 +13,9 @@ namespace Symfony\Component\CssSelector\Tests;
|
|||||||
|
|
||||||
use Symfony\Component\CssSelector\CssSelector;
|
use Symfony\Component\CssSelector\CssSelector;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group legacy
|
||||||
|
*/
|
||||||
class CssSelectorTest extends \PHPUnit_Framework_TestCase
|
class CssSelectorTest extends \PHPUnit_Framework_TestCase
|
||||||
{
|
{
|
||||||
public function testCssToXPath()
|
public function testCssToXPath()
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\DomCrawler;
|
namespace Symfony\Component\DomCrawler;
|
||||||
|
|
||||||
use Symfony\Component\CssSelector\CssSelector;
|
use Symfony\Component\CssSelector\Converter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Crawler eases navigation of a list of \DOMElement objects.
|
* Crawler eases navigation of a list of \DOMElement objects.
|
||||||
@ -42,6 +42,13 @@ class Crawler extends \SplObjectStorage
|
|||||||
*/
|
*/
|
||||||
private $baseHref;
|
private $baseHref;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the Crawler contains HTML or XML content (used when converting CSS to XPath)
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
private $isHtml = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
*
|
*
|
||||||
@ -263,6 +270,8 @@ class Crawler extends \SplObjectStorage
|
|||||||
libxml_disable_entity_loader($disableEntities);
|
libxml_disable_entity_loader($disableEntities);
|
||||||
|
|
||||||
$this->addDocument($dom);
|
$this->addDocument($dom);
|
||||||
|
|
||||||
|
$this->isHtml = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -349,11 +358,11 @@ class Crawler extends \SplObjectStorage
|
|||||||
{
|
{
|
||||||
foreach ($this as $i => $node) {
|
foreach ($this as $i => $node) {
|
||||||
if ($i == $position) {
|
if ($i == $position) {
|
||||||
return new static($node, $this->uri, $this->baseHref);
|
return $this->createSubCrawler($node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new static(null, $this->uri, $this->baseHref);
|
return $this->createSubCrawler(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -378,7 +387,7 @@ class Crawler extends \SplObjectStorage
|
|||||||
{
|
{
|
||||||
$data = array();
|
$data = array();
|
||||||
foreach ($this as $i => $node) {
|
foreach ($this as $i => $node) {
|
||||||
$data[] = $closure(new static($node, $this->uri, $this->baseHref), $i);
|
$data[] = $closure($this->createSubCrawler($node), $i);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
@ -394,7 +403,7 @@ class Crawler extends \SplObjectStorage
|
|||||||
*/
|
*/
|
||||||
public function slice($offset = 0, $length = -1)
|
public function slice($offset = 0, $length = -1)
|
||||||
{
|
{
|
||||||
return new static(iterator_to_array(new \LimitIterator($this, $offset, $length)), $this->uri);
|
return $this->createSubCrawler(iterator_to_array(new \LimitIterator($this, $offset, $length)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -412,12 +421,12 @@ class Crawler extends \SplObjectStorage
|
|||||||
{
|
{
|
||||||
$nodes = array();
|
$nodes = array();
|
||||||
foreach ($this as $i => $node) {
|
foreach ($this as $i => $node) {
|
||||||
if (false !== $closure(new static($node, $this->uri, $this->baseHref), $i)) {
|
if (false !== $closure($this->createSubCrawler($node), $i)) {
|
||||||
$nodes[] = $node;
|
$nodes[] = $node;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new static($nodes, $this->uri, $this->baseHref);
|
return $this->createSubCrawler($nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -459,7 +468,7 @@ class Crawler extends \SplObjectStorage
|
|||||||
throw new \InvalidArgumentException('The current node list is empty.');
|
throw new \InvalidArgumentException('The current node list is empty.');
|
||||||
}
|
}
|
||||||
|
|
||||||
return new static($this->sibling($this->getNode(0)->parentNode->firstChild), $this->uri, $this->baseHref);
|
return $this->createSubCrawler($this->sibling($this->getNode(0)->parentNode->firstChild));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -477,7 +486,7 @@ class Crawler extends \SplObjectStorage
|
|||||||
throw new \InvalidArgumentException('The current node list is empty.');
|
throw new \InvalidArgumentException('The current node list is empty.');
|
||||||
}
|
}
|
||||||
|
|
||||||
return new static($this->sibling($this->getNode(0)), $this->uri, $this->baseHref);
|
return $this->createSubCrawler($this->sibling($this->getNode(0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -495,7 +504,7 @@ class Crawler extends \SplObjectStorage
|
|||||||
throw new \InvalidArgumentException('The current node list is empty.');
|
throw new \InvalidArgumentException('The current node list is empty.');
|
||||||
}
|
}
|
||||||
|
|
||||||
return new static($this->sibling($this->getNode(0), 'previousSibling'), $this->uri, $this->baseHref);
|
return $this->createSubCrawler($this->sibling($this->getNode(0), 'previousSibling'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -522,7 +531,7 @@ class Crawler extends \SplObjectStorage
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new static($nodes, $this->uri, $this->baseHref);
|
return $this->createSubCrawler($nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -542,7 +551,7 @@ class Crawler extends \SplObjectStorage
|
|||||||
|
|
||||||
$node = $this->getNode(0)->firstChild;
|
$node = $this->getNode(0)->firstChild;
|
||||||
|
|
||||||
return new static($node ? $this->sibling($node) : array(), $this->uri, $this->baseHref);
|
return $this->createSubCrawler($node ? $this->sibling($node) : array());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -679,7 +688,7 @@ class Crawler extends \SplObjectStorage
|
|||||||
|
|
||||||
// If we dropped all expressions in the XPath while preparing it, there would be no match
|
// If we dropped all expressions in the XPath while preparing it, there would be no match
|
||||||
if ('' === $xpath) {
|
if ('' === $xpath) {
|
||||||
return new static(null, $this->uri, $this->baseHref);
|
return $this->createSubCrawler(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->filterRelativeXPath($xpath);
|
return $this->filterRelativeXPath($xpath);
|
||||||
@ -700,12 +709,14 @@ class Crawler extends \SplObjectStorage
|
|||||||
*/
|
*/
|
||||||
public function filter($selector)
|
public function filter($selector)
|
||||||
{
|
{
|
||||||
if (!class_exists('Symfony\\Component\\CssSelector\\CssSelector')) {
|
if (!class_exists('Symfony\\Component\\CssSelector\\Converter')) {
|
||||||
throw new \RuntimeException('Unable to filter with a CSS selector as the Symfony CssSelector is not installed (you can use filterXPath instead).');
|
throw new \RuntimeException('Unable to filter with a CSS selector as the Symfony CssSelector 2.8+ is not installed (you can use filterXPath instead).');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$converter = new Converter($this->isHtml);
|
||||||
|
|
||||||
// The CssSelector already prefixes the selector with descendant-or-self::
|
// The CssSelector already prefixes the selector with descendant-or-self::
|
||||||
return $this->filterRelativeXPath(CssSelector::toXPath($selector));
|
return $this->filterRelativeXPath($converter->toXPath($selector));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1019,7 +1030,7 @@ class Crawler extends \SplObjectStorage
|
|||||||
{
|
{
|
||||||
$prefixes = $this->findNamespacePrefixes($xpath);
|
$prefixes = $this->findNamespacePrefixes($xpath);
|
||||||
|
|
||||||
$crawler = new static(null, $this->uri, $this->baseHref);
|
$crawler = $this->createSubCrawler(null);
|
||||||
|
|
||||||
foreach ($this as $node) {
|
foreach ($this as $node) {
|
||||||
$domxpath = $this->createDOMXPath($node->ownerDocument, $prefixes);
|
$domxpath = $this->createDOMXPath($node->ownerDocument, $prefixes);
|
||||||
@ -1189,4 +1200,19 @@ class Crawler extends \SplObjectStorage
|
|||||||
|
|
||||||
return array();
|
return array();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a crawler for some subnodes
|
||||||
|
*
|
||||||
|
* @param \DOMElement|\DOMElement[]|\DOMNodeList|null $nodes
|
||||||
|
*
|
||||||
|
* @return static
|
||||||
|
*/
|
||||||
|
private function createSubCrawler($nodes)
|
||||||
|
{
|
||||||
|
$crawler = new static($nodes, $this->uri, $this->baseHref);
|
||||||
|
$crawler->isHtml = $this->isHtml;
|
||||||
|
|
||||||
|
return $crawler;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,6 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\DomCrawler\Tests;
|
namespace Symfony\Component\DomCrawler\Tests;
|
||||||
|
|
||||||
use Symfony\Component\CssSelector\CssSelector;
|
|
||||||
use Symfony\Component\DomCrawler\Crawler;
|
use Symfony\Component\DomCrawler\Crawler;
|
||||||
|
|
||||||
class CrawlerTest extends \PHPUnit_Framework_TestCase
|
class CrawlerTest extends \PHPUnit_Framework_TestCase
|
||||||
@ -618,16 +617,12 @@ EOF
|
|||||||
|
|
||||||
public function testFilterWithNamespace()
|
public function testFilterWithNamespace()
|
||||||
{
|
{
|
||||||
CssSelector::disableHtmlExtension();
|
|
||||||
|
|
||||||
$crawler = $this->createTestXmlCrawler()->filter('yt|accessControl');
|
$crawler = $this->createTestXmlCrawler()->filter('yt|accessControl');
|
||||||
$this->assertCount(2, $crawler, '->filter() automatically registers namespaces');
|
$this->assertCount(2, $crawler, '->filter() automatically registers namespaces');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testFilterWithMultipleNamespaces()
|
public function testFilterWithMultipleNamespaces()
|
||||||
{
|
{
|
||||||
CssSelector::disableHtmlExtension();
|
|
||||||
|
|
||||||
$crawler = $this->createTestXmlCrawler()->filter('media|group yt|aspectRatio');
|
$crawler = $this->createTestXmlCrawler()->filter('media|group yt|aspectRatio');
|
||||||
$this->assertCount(1, $crawler, '->filter() automatically registers namespaces');
|
$this->assertCount(1, $crawler, '->filter() automatically registers namespaces');
|
||||||
$this->assertSame('widescreen', $crawler->text());
|
$this->assertSame('widescreen', $crawler->text());
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"symfony/phpunit-bridge": "~2.7|~3.0.0",
|
"symfony/phpunit-bridge": "~2.7|~3.0.0",
|
||||||
"symfony/css-selector": "~2.3|~3.0.0"
|
"symfony/css-selector": "~2.8|~3.0.0"
|
||||||
},
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
"symfony/css-selector": ""
|
"symfony/css-selector": ""
|
||||||
|
Reference in New Issue
Block a user