Skip to content

Commit c6fbb13

Browse files
committed
[DomCrawler] Added support for an automatic default namespace registration.
1 parent 587e2dd commit c6fbb13

File tree

2 files changed

+52
-12
lines changed

2 files changed

+52
-12
lines changed

src/Symfony/Component/DomCrawler/Crawler.php

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -577,16 +577,8 @@ public function filterXPath($xpath)
577577
$root->appendChild($document->importNode($node, true));
578578
}
579579

580-
$domxpath = new \DOMXPath($document);
581-
if (preg_match_all('/(?P<prefix>[a-zA-Z_][a-zA-Z_0-9\-\.]+):[^:]/', $xpath, $matches)) {
582-
foreach ($matches['prefix'] as $prefix) {
583-
// ask for one namespace, otherwise we'd get a collection with an item for each node
584-
$namespaces = $domxpath->query(sprintf('(//namespace::*[name()="%s"])[last()]', $prefix));
585-
foreach ($namespaces as $node) {
586-
$domxpath->registerNamespace($node->prefix, $node->nodeValue);
587-
}
588-
}
589-
}
580+
$prefixes = $this->findNamespacePrefixes($xpath);
581+
$domxpath = $this->createDOMXPath($document, $prefixes);
590582

591583
return new static($domxpath->query($xpath), $this->uri);
592584
}
@@ -799,4 +791,43 @@ protected function sibling($node, $siblingDir = 'nextSibling')
799791

800792
return $nodes;
801793
}
794+
795+
/**
796+
* @param \DOMDocument $document
797+
* @param array $prefixes
798+
*
799+
* @return \DOMXPath
800+
*
801+
* @throws \InvalidArgumentException
802+
*/
803+
private function createDOMXPath(\DOMDocument $document, array $prefixes = array())
804+
{
805+
$domxpath = new \DOMXPath($document);
806+
807+
foreach ($prefixes as $prefix) {
808+
// ask for one namespace, otherwise we'd get a collection with an item for each node
809+
$namespaces = $domxpath->query(sprintf('(//namespace::*[name()="%s"])[last()]', 'default' === $prefix ? '' : $prefix));
810+
if ($node = $namespaces->item(0)) {
811+
$domxpath->registerNamespace($prefix, $node->nodeValue);
812+
} else {
813+
throw new \InvalidArgumentException(sprintf('Could not find a namespace for the prefix: "%s"', $prefix));
814+
}
815+
}
816+
817+
return $domxpath;
818+
}
819+
820+
/**
821+
* @param $xpath
822+
*
823+
* @return array
824+
*/
825+
private function findNamespacePrefixes($xpath)
826+
{
827+
if (preg_match_all('/(?P<prefix>[a-zA-Z_][a-zA-Z_0-9\-\.]+):[^:]/', $xpath, $matches)) {
828+
return array_unique($matches['prefix']);
829+
}
830+
831+
return array();
832+
}
802833
}

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

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,7 @@ public function testFilterXPath()
373373

374374
public function testFilterXPathWithDefaultNamespace()
375375
{
376-
$crawler = $this->createTestXmlCrawler()->filterXPath('//entry/id');
376+
$crawler = $this->createTestXmlCrawler()->filterXPath('//default:entry/default:id');
377377
$this->assertCount(1, $crawler, '->filterXPath() automatically registers a namespace');
378378
$this->assertSame('tag:youtube.com,2008:video:kgZRZmEc9j4', $crawler->text());
379379
}
@@ -391,6 +391,15 @@ public function testFilterXPathWithMultipleNamespaces()
391391
$this->assertSame('widescreen', $crawler->text());
392392
}
393393

394+
/**
395+
* @expectedException \InvalidArgumentException
396+
* @expectedExceptionMessage Could not find a namespace for the prefix: "foo"
397+
*/
398+
public function testFilterXPathWithAnInvalidNamespace()
399+
{
400+
$this->createTestXmlCrawler()->filterXPath('//media:group/foo:aspectRatio');
401+
}
402+
394403
/**
395404
* @covers Symfony\Component\DomCrawler\Crawler::filter
396405
*/
@@ -411,7 +420,7 @@ public function testFilterWithDefaultNamespace()
411420
{
412421
$this->markSkippedIfCssSelectorNotPresent();
413422

414-
$crawler = $this->createTestXmlCrawler()->filter('entry id');
423+
$crawler = $this->createTestXmlCrawler()->filter('default|entry default|id');
415424
$this->assertCount(1, $crawler, '->filter() automatically registers namespaces');
416425
$this->assertSame('tag:youtube.com,2008:video:kgZRZmEc9j4', $crawler->text());
417426
}

0 commit comments

Comments
 (0)