[DomCrawler] Added support for an automatic default namespace registration.
This commit is contained in:
parent
587e2dd44f
commit
c6fbb13938
@ -577,16 +577,8 @@ class Crawler extends \SplObjectStorage
|
|||||||
$root->appendChild($document->importNode($node, true));
|
$root->appendChild($document->importNode($node, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
$domxpath = new \DOMXPath($document);
|
$prefixes = $this->findNamespacePrefixes($xpath);
|
||||||
if (preg_match_all('/(?P<prefix>[a-zA-Z_][a-zA-Z_0-9\-\.]+):[^:]/', $xpath, $matches)) {
|
$domxpath = $this->createDOMXPath($document, $prefixes);
|
||||||
foreach ($matches['prefix'] as $prefix) {
|
|
||||||
// ask for one namespace, otherwise we'd get a collection with an item for each node
|
|
||||||
$namespaces = $domxpath->query(sprintf('(//namespace::*[name()="%s"])[last()]', $prefix));
|
|
||||||
foreach ($namespaces as $node) {
|
|
||||||
$domxpath->registerNamespace($node->prefix, $node->nodeValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new static($domxpath->query($xpath), $this->uri);
|
return new static($domxpath->query($xpath), $this->uri);
|
||||||
}
|
}
|
||||||
@ -799,4 +791,43 @@ class Crawler extends \SplObjectStorage
|
|||||||
|
|
||||||
return $nodes;
|
return $nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \DOMDocument $document
|
||||||
|
* @param array $prefixes
|
||||||
|
*
|
||||||
|
* @return \DOMXPath
|
||||||
|
*
|
||||||
|
* @throws \InvalidArgumentException
|
||||||
|
*/
|
||||||
|
private function createDOMXPath(\DOMDocument $document, array $prefixes = array())
|
||||||
|
{
|
||||||
|
$domxpath = new \DOMXPath($document);
|
||||||
|
|
||||||
|
foreach ($prefixes as $prefix) {
|
||||||
|
// ask for one namespace, otherwise we'd get a collection with an item for each node
|
||||||
|
$namespaces = $domxpath->query(sprintf('(//namespace::*[name()="%s"])[last()]', 'default' === $prefix ? '' : $prefix));
|
||||||
|
if ($node = $namespaces->item(0)) {
|
||||||
|
$domxpath->registerNamespace($prefix, $node->nodeValue);
|
||||||
|
} else {
|
||||||
|
throw new \InvalidArgumentException(sprintf('Could not find a namespace for the prefix: "%s"', $prefix));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $domxpath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $xpath
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function findNamespacePrefixes($xpath)
|
||||||
|
{
|
||||||
|
if (preg_match_all('/(?P<prefix>[a-zA-Z_][a-zA-Z_0-9\-\.]+):[^:]/', $xpath, $matches)) {
|
||||||
|
return array_unique($matches['prefix']);
|
||||||
|
}
|
||||||
|
|
||||||
|
return array();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -373,7 +373,7 @@ EOF
|
|||||||
|
|
||||||
public function testFilterXPathWithDefaultNamespace()
|
public function testFilterXPathWithDefaultNamespace()
|
||||||
{
|
{
|
||||||
$crawler = $this->createTestXmlCrawler()->filterXPath('//entry/id');
|
$crawler = $this->createTestXmlCrawler()->filterXPath('//default:entry/default:id');
|
||||||
$this->assertCount(1, $crawler, '->filterXPath() automatically registers a namespace');
|
$this->assertCount(1, $crawler, '->filterXPath() automatically registers a namespace');
|
||||||
$this->assertSame('tag:youtube.com,2008:video:kgZRZmEc9j4', $crawler->text());
|
$this->assertSame('tag:youtube.com,2008:video:kgZRZmEc9j4', $crawler->text());
|
||||||
}
|
}
|
||||||
@ -391,6 +391,15 @@ EOF
|
|||||||
$this->assertSame('widescreen', $crawler->text());
|
$this->assertSame('widescreen', $crawler->text());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \InvalidArgumentException
|
||||||
|
* @expectedExceptionMessage Could not find a namespace for the prefix: "foo"
|
||||||
|
*/
|
||||||
|
public function testFilterXPathWithAnInvalidNamespace()
|
||||||
|
{
|
||||||
|
$this->createTestXmlCrawler()->filterXPath('//media:group/foo:aspectRatio');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @covers Symfony\Component\DomCrawler\Crawler::filter
|
* @covers Symfony\Component\DomCrawler\Crawler::filter
|
||||||
*/
|
*/
|
||||||
@ -411,7 +420,7 @@ EOF
|
|||||||
{
|
{
|
||||||
$this->markSkippedIfCssSelectorNotPresent();
|
$this->markSkippedIfCssSelectorNotPresent();
|
||||||
|
|
||||||
$crawler = $this->createTestXmlCrawler()->filter('entry id');
|
$crawler = $this->createTestXmlCrawler()->filter('default|entry default|id');
|
||||||
$this->assertCount(1, $crawler, '->filter() automatically registers namespaces');
|
$this->assertCount(1, $crawler, '->filter() automatically registers namespaces');
|
||||||
$this->assertSame('tag:youtube.com,2008:video:kgZRZmEc9j4', $crawler->text());
|
$this->assertSame('tag:youtube.com,2008:video:kgZRZmEc9j4', $crawler->text());
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user