/** * Parse the HTML */ protected function parse() { // Buffers $current_tag_buffer = array(); $buffer_parent = $this->_document; $buffer_last_tag = ''; // Do the split $len = strlen($this->_html); for ($i = 0; $i < $len; $i++) { $chr = $this->_html[$i]; // Have we hit a new tag? if ($chr == '<') { $closing = false; $saved_i = $i; $tag_name = $this->parseTagName($i, $closing); $tag_attrs = array(); if (!$closing && $this->_html[$i] == ' ') { $tag_attrs = $this->parseAttributes($i, $closing); } // Are we to close something? if ($closing) { // Are we expecting this to be closed? if ($tag_name !== $buffer_last_tag) { throw new \Exception("Parser error: Encountered closing " . $tag_name . " was expecting " . $buffer_last_tag); } // Store contents $start = $current_tag_buffer[spl_object_hash($buffer_parent)]; $buffer_parent->setContents(substr($this->_html, $start, $saved_i - $start)); // We want to go back a bit $buffer_parent = $buffer_parent->parent(); if (!$buffer_parent) { $buffer_parent = $this->_document; } $buffer_last_tag = $buffer_parent->name(); continue; } // Are we to create something? if (!$closing) { if (!$this->_document) { $buffer_parent = $this->_document = PureTree::buildRoot($tag_name, $tag_attrs); } else { $buffer_parent = $buffer_parent->createChild($tag_name, $tag_attrs); } $current_tag_buffer[spl_object_hash($buffer_parent)] = $i + 1; // Is this a self closing tag? if ($this->_html[$i] == "/") { $i++; $buffer_parent = $buffer_parent->parent(); if (!$buffer_parent) { $buffer_parent = $this->_document; } continue; } $buffer_last_tag = $tag_name; continue; } $i++; } } }
public function test_TreeQuery() { $root = PureTree::buildRoot('html', array(), '<head><title>Welcome</title></head><body><h1>Lorum!</h1><p>String 1</p><p>String 2 <span>Example</span></p></body></html'); $head = $root->createChild("head", array(), '<title>Welcome</title>'); $title = $head->createChild("title", array(), 'Welcome'); $body = $root->createChild("body", array(), '<h1>Lorum!</h1><p>String 1</p><p>String 2</p>'); $h1 = $body->createChild("h1", array(), 'Lorum!'); $p1 = $body->createChild("p", array(), 'String 1'); $p2 = $body->createChild("p", array(), 'String 2 <span>Example</span>'); $span = $p2->createChild("span", array(), 'Example'); // Now test querying $result = $root->query("title"); $this->assertEquals(1, count($result)); $this->assertEquals($title, $result); // More complex query $result = $root->query("html > head > title"); $this->assertEquals(1, count($result)); $this->assertEquals($title, $result); // Another query $result = $root->query("html head title"); $this->assertEquals(1, count($result)); $this->assertEquals($title, $result); // Another query $result = $root->query("html title"); $this->assertEquals(1, count($result)); $this->assertEquals($title, $result); // Another query $result = $root->query("head > title"); $this->assertEquals(1, count($result)); $this->assertEquals($title, $result); // Another query $result = $root->query("head"); $this->assertEquals(1, count($result)); $this->assertEquals($head, $result); // Test the '>' priorities $result = $root->query("body > span"); $this->assertEquals(null, $result); // Test the '+' priorities $result = $root->query("h1 + p"); $this->assertEquals($p1, $result); }
public function test_runPath() { $root = PureTree::buildRoot('html', array(), ''); $head = $root->createChild("head", array(), ''); $title = $head->createChild("title", array(), ''); $body = $root->createChild("body", array(), ''); $h1 = $body->createChild("h1", array("class" => "ipsum"), ''); $p1 = $body->createChild("p", array("id" => "example"), ''); $p2 = $body->createChild("p", array("class" => "example lorum"), ''); $p3 = $p2->createChild("p", array("class" => "lorum"), ''); $p4 = $p2->createChild("p", array("class" => "ipsum singleton", "data-select" => "me"), ''); $query = new TestableQuery("html"); $result = $query->run($root); $this->assertEquals(array($root), $result); $query = new TestableQuery("p"); $result = $query->run($root); $this->assertEquals(4, count($result)); $query = new TestableQuery("html title"); $result = $query->run($root); $this->assertEquals(array($title), $result); $query = new TestableQuery("html html"); $result = $query->run($root); $this->assertEquals(0, count($result)); $query = new TestableQuery("p p"); $result = $query->run($root); $this->assertEquals(array($p3, $p4), $result); $query = new TestableQuery("html body h1"); $result = $query->run($root); $this->assertEquals(array($h1), $result); // Selector magic $query = new TestableQuery("html > title"); $result = $query->run($root); $this->assertEquals(0, count($result)); $query = new TestableQuery("html > head"); $result = $query->run($root); $this->assertEquals(array($head), $result); $query = new TestableQuery("html > head > title"); $result = $query->run($root); $this->assertEquals(array($title), $result); $query = new TestableQuery("html body h1 + p"); $result = $query->run($root); $this->assertEquals(array($p1), $result); $query = new TestableQuery("h1 + p"); $result = $query->run($root); $this->assertEquals(array($p1), $result); $query = new TestableQuery("p + p"); $result = $query->run($root); $this->assertEquals(array($p2, $p4), $result); $query = new TestableQuery("p *"); $result = $query->run($root); $this->assertEquals(array($p3, $p4), $result); $query = new TestableQuery("html > head *"); $result = $query->run($root); $this->assertEquals(array($title), $result); $query = new TestableQuery("*"); $result = $query->run($root); $this->assertEquals(9, count($result)); $query = new TestableQuery("#example"); $result = $query->run($root); $this->assertEquals(array($p1), $result); $query = new TestableQuery(".example"); $result = $query->run($root); $this->assertEquals(array($p2), $result); $query = new TestableQuery(".lorum"); $result = $query->run($root); $this->assertEquals(array($p2, $p3), $result); $query = new TestableQuery("body .lorum"); $result = $query->run($root); $this->assertEquals(array($p2, $p3), $result); $query = new TestableQuery("html > body .lorum"); $result = $query->run($root); $this->assertEquals(array($p2, $p3), $result); $query = new TestableQuery("body > .lorum"); $result = $query->run($root); $this->assertEquals(array($p2), $result); $query = new TestableQuery("* > .lorum"); $result = $query->run($root); $this->assertEquals(array($p2, $p3), $result); $query = new TestableQuery("* .lorum"); $result = $query->run($root); $this->assertEquals(array($p2, $p3), $result); $query = new TestableQuery("p.ipsum"); $result = $query->run($root); $this->assertEquals(array($p4), $result); $query = new TestableQuery("body > h1.ipsum"); $result = $query->run($root); $this->assertEquals(array($h1), $result); $query = new TestableQuery("body > p.example.lorum"); $result = $query->run($root); $this->assertEquals(array($p2), $result); $query = new TestableQuery("p.example.lorum"); $result = $query->run($root); $this->assertEquals(array($p2), $result); $query = new TestableQuery("p:first-child"); $result = $query->run($root); $this->assertEquals(array($p3), $result); $query = new TestableQuery("p.lorum:first-child"); $result = $query->run($root); $this->assertEquals(array($p3), $result); $query = new TestableQuery("body *:first-child"); $result = $query->run($root); $this->assertEquals(array($h1, $p3), $result); $query = new TestableQuery("body > *:first-child"); $result = $query->run($root); $this->assertEquals(array($h1), $result); $query = new TestableQuery("p:last-child"); $result = $query->run($root); $this->assertEquals(array($p2, $p4), $result); $query = new TestableQuery("body p:last-child"); $result = $query->run($root); $this->assertEquals(array($p2, $p4), $result); $query = new TestableQuery("body > p:last-child"); $result = $query->run($root); $this->assertEquals(array($p2), $result); $query = new TestableQuery("body *:nth-child(0)"); $result = $query->run($root); $this->assertEquals(array($h1, $p3), $result); $query = new TestableQuery("body p:nth-child(1)"); $result = $query->run($root); $this->assertEquals(array($p1, $p4), $result); $query = new TestableQuery("body p:nth-child(even)"); $result = $query->run($root); $this->assertEquals(array($p2, $p3), $result); $query = new TestableQuery("body p:nth-child(odd)"); $result = $query->run($root); $this->assertEquals(array($p1, $p4), $result); $query = new TestableQuery("body p[data-select=me]"); $result = $query->run($root); $this->assertEquals(array($p4), $result); $query = new TestableQuery("p[data-select=me]"); $result = $query->run($root); $this->assertEquals(array($p4), $result); $query = new TestableQuery("p[data-select=me,class=ipsum]"); $result = $query->run($root); $this->assertEquals(array($p4), $result); $query = new TestableQuery("p[class=ipsum+singleton]"); $result = $query->run($root); $this->assertEquals(array($p4), $result); $query = new TestableQuery("p > p[data-select=me,class=ipsum+singleton]:last-child"); $result = $query->run($root); $this->assertEquals(array($p4), $result); }