@@ -33,6 +33,11 @@ class Crawler implements \Countable, \IteratorAggregate
33
33
*/
34
34
private $ namespaces = [];
35
35
36
+ /**
37
+ * @var \ArrayIterator A map of cached namespaces
38
+ */
39
+ private $ cachedNamespaces ;
40
+
36
41
/**
37
42
* @var string The base href value
38
43
*/
@@ -68,6 +73,7 @@ public function __construct($node = null, string $uri = null, string $baseHref =
68
73
$ this ->uri = $ uri ;
69
74
$ this ->baseHref = $ baseHref ?: $ uri ;
70
75
$ this ->html5Parser = class_exists (HTML5 ::class) ? new HTML5 (['disable_html_ns ' => true ]) : null ;
76
+ $ this ->cachedNamespaces = new \ArrayIterator ();
71
77
72
78
$ this ->add ($ node );
73
79
}
@@ -99,6 +105,7 @@ public function clear()
99
105
{
100
106
$ this ->nodes = [];
101
107
$ this ->document = null ;
108
+ $ this ->cachedNamespaces = new \ArrayIterator ();
102
109
}
103
110
104
111
/**
@@ -967,12 +974,14 @@ public static function xpathLiteral(string $s)
967
974
*/
968
975
private function filterRelativeXPath (string $ xpath ): object
969
976
{
970
- $ prefixes = $ this ->findNamespacePrefixes ($ xpath );
971
-
972
977
$ crawler = $ this ->createSubCrawler (null );
978
+ if (null === $ this ->document ) {
979
+ return $ crawler ;
980
+ }
981
+
982
+ $ domxpath = $ this ->createDOMXPath ($ this ->document , $ this ->findNamespacePrefixes ($ xpath ));
973
983
974
984
foreach ($ this ->nodes as $ node ) {
975
- $ domxpath = $ this ->createDOMXPath ($ node ->ownerDocument , $ prefixes );
976
985
$ crawler ->add ($ domxpath ->query ($ xpath , $ node ));
977
986
}
978
987
@@ -1189,10 +1198,17 @@ private function discoverNamespace(\DOMXPath $domxpath, string $prefix): ?string
1189
1198
return $ this ->namespaces [$ prefix ];
1190
1199
}
1191
1200
1201
+ if ($ this ->cachedNamespaces ->offsetExists ($ prefix )) {
1202
+ return $ this ->cachedNamespaces ->offsetGet ($ prefix );
1203
+ }
1204
+
1192
1205
// ask for one namespace, otherwise we'd get a collection with an item for each node
1193
1206
$ namespaces = $ domxpath ->query (sprintf ('(//namespace::*[name()="%s"])[last()] ' , $ this ->defaultNamespacePrefix === $ prefix ? '' : $ prefix ));
1194
1207
1195
- return ($ node = $ namespaces ->item (0 )) ? $ node ->nodeValue : null ;
1208
+ $ namespace = ($ node = $ namespaces ->item (0 )) ? $ node ->nodeValue : null ;
1209
+ $ this ->cachedNamespaces ->offsetSet ($ prefix , $ namespace );
1210
+
1211
+ return $ namespace ;
1196
1212
}
1197
1213
1198
1214
private function findNamespacePrefixes (string $ xpath ): array
@@ -1217,6 +1233,7 @@ private function createSubCrawler($nodes): object
1217
1233
$ crawler ->isHtml = $ this ->isHtml ;
1218
1234
$ crawler ->document = $ this ->document ;
1219
1235
$ crawler ->namespaces = $ this ->namespaces ;
1236
+ $ crawler ->cachedNamespaces = $ this ->cachedNamespaces ;
1220
1237
$ crawler ->html5Parser = $ this ->html5Parser ;
1221
1238
1222
1239
return $ crawler ;
0 commit comments