Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Addressed bug in my implementation of :contains(), added contains-exa…

…ctly().

Previous versions of :contains() looked for an exact match in
PCDATA. Now, to match jQuery, we do a substring match. The new
:contains-exactly() pseudoclass performs the task formerly
handled by :contains(). Issue #32.
  • Loading branch information...
commit b1d4b70e9b06e72ac38b22c15d9b5e6dd19bd848 1 parent bbc739d
@technosophos technosophos authored
View
4 examples/matching_text_content.php
@@ -8,6 +8,10 @@
* to match just part of the contents of an element. This example
* illustrates how to accomplish this with a filter callback.
*
+ * As of QueryPath 2.1beta2, `:contains()` performs a substring match instead of
+ * and exact match, so the method outline below is roughly the same as merely
+ * using `:contains(Release)`.
+ *
* @package Examples
* @author M Butcher <matt@aleph-null.tv>
* @license LGPL The GNU Lesser GPL (LGPL) or an MIT-like license.
View
15 src/QueryPath/CssEventHandler.php
@@ -563,8 +563,23 @@ public function pseudoClass($name, $value = NULL) {
$this->has($value);
break;
// Contains == text matches.
+ // In QP 2.1, this was changed.
case 'contains':
$value = $this->removeQuotes($value);
+
+ $matches = $this->candidateList();
+ $found = new SplObjectStorage();
+ foreach ($matches as $item) {
+ if (strpos($item->textContent, $value) !== FALSE) {
+ $found->attach($item);
+ }
+ }
+ $this->matches = $found;
+ break;
+
+ // Since QP 2.1
+ case 'contains-exactly':
+ $value = $this->removeQuotes($value);
$matches = $this->candidateList();
$found = new SplObjectStorage();
View
48 test/Tests/QueryPath/CssEventTest.php
@@ -1106,7 +1106,7 @@ public function testPseudoClassContains() {
$doc->loadXML($xml);
$handler = new QueryPathCssEventHandler($doc);
- $handler->find(':contains(This is text.)');
+ $handler->find('p:contains(This is text.)');
$matches = $handler->getMatches();
$this->assertEquals(1, $matches->count());
$this->assertEquals('one', $this->firstMatch($matches)->getAttribute('id'));
@@ -1114,24 +1114,64 @@ public function testPseudoClassContains() {
$handler = new QueryPathCssEventHandler($doc);
$handler->find('* :contains(More text)');
$matches = $handler->getMatches();
- $this->assertEquals(2, $matches->count());
+ $this->assertEquals(2, $matches->count(), 'Matches two instance of same text?');
$this->assertEquals('two', $this->firstMatch($matches)->getAttribute('id'));
$handler = new QueryPathCssEventHandler($doc);
- $handler->find(':contains("This is text.")');
+ $handler->find('p:contains("This is text.")');
$matches = $handler->getMatches();
$this->assertEquals(1, $matches->count(), 'Quoted text matches unquoted pcdata');
$this->assertEquals('one', $this->firstMatch($matches)->getAttribute('id'));
$handler = new QueryPathCssEventHandler($doc);
- $handler->find(':contains(\\\'This is text.\\\')');
+ $handler->find('p:contains(\\\'This is text.\\\')');
$matches = $handler->getMatches();
$this->assertEquals(1, $matches->count(), 'One match for quoted string.');
$this->assertEquals('one', $this->firstMatch($matches)->getAttribute('id'));
+ // Test for issue #32
+ $handler = new QueryPathCssEventHandler($doc);
+ $handler->find('p:contains(text)');
+ $matches = $handler->getMatches();
+ $this->assertEquals(2, $matches->count(), 'Two matches for fragment of string.');
+ $this->assertEquals('one', $this->firstMatch($matches)->getAttribute('id'));
}
+ public function testPseudoClassContainsExactly() {
+ $xml = '<?xml version="1.0" ?>
+ <test>
+ <p id="one">This is text.</p>
+ <p id="two"><i>More text</i></p>
+ </test>';
+ $doc = new DomDocument();
+ $doc->loadXML($xml);
+
+ $handler = new QueryPathCssEventHandler($doc);
+ $handler->find('p:contains(This is text.)');
+ $matches = $handler->getMatches();
+ $this->assertEquals(1, $matches->count());
+ $this->assertEquals('one', $this->firstMatch($matches)->getAttribute('id'));
+
+ $handler = new QueryPathCssEventHandler($doc);
+ $handler->find('* :contains(More text)');
+ $matches = $handler->getMatches();
+ $this->assertEquals(2, $matches->count(), 'Matches two instance of same text.');
+ $this->assertEquals('two', $this->firstMatch($matches)->getAttribute('id'));
+
+ $handler = new QueryPathCssEventHandler($doc);
+ $handler->find('p:contains("This is text.")');
+ $matches = $handler->getMatches();
+ $this->assertEquals(1, $matches->count(), 'Quoted text matches unquoted pcdata');
+ $this->assertEquals('one', $this->firstMatch($matches)->getAttribute('id'));
+
+ $handler = new QueryPathCssEventHandler($doc);
+ $handler->find('p:contains(\\\'This is text.\\\')');
+ $matches = $handler->getMatches();
+ $this->assertEquals(1, $matches->count(), 'One match for quoted string.');
+ $this->assertEquals('one', $this->firstMatch($matches)->getAttribute('id'));
+ }
+
public function testPseudoClassHas() {
$xml = '<?xml version="1.0" ?>
<test>
View
5 tutorials/QueryPath/csspseudo.pkg
@@ -36,7 +36,7 @@
<listitem>:root()</listitem>
<listitem>:nth-child(an + b) </listitem>
<listitem>:nth-last-child(an + b)</listitem>
- <listitem>:nth-of-type(an + b) -- as of QuerPath 'quark'</listitem>
+ <listitem>:nth-of-type(an + b) -- as of QuerPath 'quark' (2.0)</listitem>
<listitem>:nth-last-of-type(an + b) -- as of QuerPath 'quark'</listitem>
<listitem>:first-child</listitem>
<listitem>:last-child</listitem>
@@ -85,7 +85,8 @@
<listitem>:reset -- element is reset button (HTML only)</listitem>
<listitem>:header -- elements that are HTML headers (h1 - hN)</listitem>
<listitem>:has(some filter) -- elements that have children that match the supplied filter</listitem>
- <listitem>:contains(some text) -- elements that have text which matches the supplied value</listitem>
+ <listitem>:contains(some text) -- elements that have text of which some substring matches the supplied value (Prior to QueryPath 2.1, this behaved identically to :contains-exactly)</listitem>
+ <listitem>:contains-exactly(some text) -- elements that have text which exactly matches the supplied value (QueryPath 2.1)</listitem>
</itemizedlist>
</para>
</refsect2>
Please sign in to comment.
Something went wrong with that request. Please try again.