string function str_get_html($str, $lowercase=true) { $dom = new simple_html_dom; $dom->load($str, $lowercase); return $dom; } // dump html dom tree function dump_html_tree($node, $show_attr=true, $deep=0) { $lead = str_repeat(' ', $deep); echo $lead.$node->tag; if ($show_attr && count($node->attr)>0) { echo '('; foreach($node->attr as $k=>$v) echo "[$k]=>\"".$node->$k.'", '; echo ')'; } echo "\n"; foreach($node->nodes as $c) dump_html_tree($c, $show_attr, $deep+1); } // get dom form file (deprecated) function file_get_dom() { $dom = new simple_html_dom; $args = func_get_args(); $dom->load(call_user_func_array('file_get_contents', $args), true); return $dom; } // get dom form string (deprecated) function str_get_dom($str, $lowercase=true) { $dom = new simple_html_dom; $dom->load($str, $lowercase); return $dom; } // simple html dom node // --------------------------------------------------------- // clean up memory due to php5 circular references memory leak... function clear() { $this->dom = null; $this->nodes = null; $this->parent = null; $this->children = null; } // dump node's tree function dump($show_attr=true) { dump_html_tree($this, $show_attr); } // returns the parent of node function parent() { return $this->parent; } // returns children of node function children($idx=-1) { if ($idx===-1) return $ret; } // get dom node's outer text (with tag) function outertext() { if ($this->tag==='root') return $this->innertext(); // trigger callback if ($this->dom->callback!==null) call_user_func_array($this->dom->callback, array($this)); if (isset($this->_[HDOM_INFO_OUTER])) return $this->_[HDOM_INFO_OUTER]; if (isset($this->_[HDOM_INFO_TEXT])) return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]); // render begin tagr as $key=>$val) { ++$i; // skip removed attribute if ($val===null || $val===false) continue; $ret .= $this->_[HDOM_INFO_SPACE][$i][0]; //no value attr: nowrap, checked selected... if ($val===true) $ret .= $key; else { switch($this->_[HDOM_INFO_QUOTE][$i]) { case HDOM_QUOTE_DOUBLE: $quote = '"'; break; case HDOM_QUOTE_SINGLE: $quote = '\''; break; default: $quote = ''; } $ret .= $key.$this->_[HDOM_INFO_SPACE][$i][1].'='.$this->_[HDOM_INFO_SPACE][$i][2].$quote.$val.$quote; } } $ret = $this->dom->restore_noise($ret); return $ret . $this->_[HDOM_INFO_ENDSPACE] . '>'; } // find elements by css selector function find($selector, $idx=null) { $selectors = $this->parse_selector($selector); if (($count=count($selectors))===0) return array(); $found_keys = array(); // find each selector for ($c=0; $c<$count; ++$c) { if (($levle=count($selectors[0]))===0) return array(); if (!isset($this->_[HDOM_INFO_BEGIN])) return array(); $head = array($this->_[HDOM_INFO_BEGIN]=>1); // handle descendant selectors, no recursive! for ($l=0; $l<$levle; ++$l) { $ret = array(); foreach($head as $k=>$v) { $n = ($k===-1) ? $this->dom->root : $this->dom->nodes[$k]; $n->seek($selectors[$c][$l], $ret); } $head = $ret; } foreach($head as $k=>$v) { if (!isset($found_keys[$k])) $found_keys[$k] = 1; } } // sort keys ksort($found_keys); $found = array(); foreach($found_keys as $k=>$v) $found[] = $this->dom->nodes[$k]; // return nth-element or array if (is_null($idx)) return $found; else if ($idx<0) $idx = count($found) + $idx; return (isset($found[$idx])) ? $found[$idx] : null; } // seek for given conditions protected function seek($selector, &$ret) { list($tag, $key, $val, $exp, $no_key) = $selector; // xpath index if ($tag && $key && is_numeric($key)) { $count = 0; foreach ($this->children as $c) { if ($tag==='*' || $tag===$c->tag) { nd += $parent->_[HDOM_INFO_END]; } for($i=$this->_[HDOM_INFO_BEGIN]+1; $i<$end; ++$i) { $node = $this->dom->nodes[$i]; $pass = true; if ($tag==='*' && !$key) { if (in_array($node, $this->children, true)) $ret[$i] = 1; continue; } // compare tag if ($tag && $tag!=$node->tag && $tag!=='*') {$pass=false;} // compare key if ($pass && $key) { if ($no_key) { if (isset($node->attr[$key])) $pass=false; } else if (!isset($node->attr[$key])) $pass=false; } // compare value if ($pass && $key && $val && $val!=='*') { $check = $this->match($exp, $val, $node->attr[$key]); // handle multiple class if (!$check && strcasecmp($key, 'class')===0) { foreach(explode(' ',$node->attr[$key]) as $k) [1]==='tbody') continue; list($tag, $key, $val, $exp, $no_key) = array($m[1], null, null, '=', false); if(!empty($m[2])) {$key='id'; $val=$m[2];} if(!empty($m[3])) {$key='class'; $val=$m[3];} if(!empty($m[4])) {$key=$m[4];} if(!empty($m[5])) {$exp=$m[5];} if(!empty($m[6])) {$val=$m[6];} // convert to lowercase if ($this->dom->lowercase) {$tag=strtolower($tag); $key=strtolower($key);} //elements thatname]; switch($name) { case 'outertext': return $this->outertext(); case 'innertext': return $this->innertext(); case 'plaintext': return $this->text(); case 'xmltext': return $this->xmltext(); default: return array_key_exists($name, $this->attr); } } function __set($name, $value) { switch($name) { case 'outertext': return $this->_[HDOM_INFO_OUTER] = $value; case 'innertext': if (isset($this->_[HDOM_INFO_TEXT])) return $this->_[HDOM_INFO_TEXT] = $value; return $this->_[HDOM_INFO_INNER] = $value; } if (!isset($this->attr[$name])) { $this->_[HDOM_INFO_SPACE][] = array(' ', '', ''); $this->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_DOUBLE; } $this->attr[$name] = $value; } function __isset($name) { switch($name) { case 'outertext': return true; case 'innertext': return true; __set($name, $value);} function hasAttribute($name) {return $this->__isset($name);} function removeAttribute($name) {$this->__set($name, null);} function getElementById($id) {return $this->find("#$id", 0);} function getElementsById($id, $idx=null) {return $this->find("#$id", $idx);} function getElementByTagName($name) {return $this->find($name, 0);} function getElementsByTagName($name, $idx=null) {return $this->find($name, $idx);} function parentNode() {return $this->parent();} his->remove_noise("'<\s*(?:code)[^>]*>(.*?)<\s*/\s*(?:code)\s*>'is"); // strip out server side scripts $this->remove_noise("'(<\?)(.*?)(\?>)'s", true); // strip smarty scripts $this->remove_noise("'(\{\w)(.*?)(\})'s", true); // parsing while ($this->parse()); // end $this->root->_[HDOM_INFO_END] = $this->cursor; } // load html from file function load_file() { $args = func_get_args(); $this->load(call_user_func_arra $this->root->dump($show_attr); } // prepare HTML data and init everything protected function prepare($str, $lowercase=true) { $this->clear(); $this->doc = $str; $this->pos = 0; $this->cursor = 1; $this->noise = array(); $this->nodes = array(); $this->lowercase = $lowercase; $this->root = new simple_html_dom_node($this); $this->root->tag = 'root'; $this->root->_[HDOM_INFO_BEGIN] = -1; $this->root->nodetype return true; } // read tag info protected function read_tag() { if ($this->char!=='<') { $this->root->_[HDOM_INFO_END] = $this->cursor; return false; } $begin_tag_pos = $this->pos; $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next // end tag if ($this->char==='/') { $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next $this->skip($this->token_blank_t); $tag = $this->copy_until_char('>'); // skip attributes in end tag if (($pos = strpos($tag, ' '))!==false) $tag = substr($tag, 0, $pos); $parent_lower = strtolower($this->parent->tag); $tag_lower = strtolower($tag); if ($parent_lower!==$tag_lower) { if (isset($this->optional_closing_tags[$parent_lower]) && isset($this->block_tags[$tag_lower])) { $this->parent->_>parent->parent; } else return $this->as_text_node($tag); } $this->parent->_[HDOM_INFO_END] = $this->cursor; if ($this->parent->parent) $this->parent = $this->parent->parent; $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next return true; } $node = new simple_html_dom_node($this); $node->_[HDOM_INFO_BEGIN] = $this->cursor; ++$this-> } if ($this->char==='>') $node->_[HDOM_INFO_TEXT].='>'; $this->link_nodes($node, true); $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next return true; } // text if ($pos=strpos($tag, '<')!==false) { $tag = '<' . substr($tag, 0, -1); $node->_[HDOM_INFO_TEXT] = $tag; $this->link_nodes($node, false); $this->char = $this->doc[--$this->pos]; // prev return true; } if (!preg_match("/^[\w-:]+$/", $tag)) { $node->_[HDOM_INFO_TEXT] = '<' . $tag . $this->copy_until('<>'); if ($this->char==='<') { $this->link_nodes($node, false); return true; } if ($this->char==='>') $node->_[HDOM_INFO_TEXT].='>'; $this->link_nodes($node, false); $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next return true; } // begin tag $node->nodetype = HDOM_TYPE_ELEMENT; $tag_lower = strtolower($tag); $node->tag = ($this->lowercase) ? $tag_lower : $tag; // handle optional closing tags if (isset($this->optional_closing_tags[$tag_lower]) ) { while (isset($this->optional_closing_tags[$tag_lower][strtolower($this->parent->tag)])) { $this->parent->_[HDOM_INFO_END] = 0; $this->parent = $this->parent->parent; } $node->parent = $this->parent; } $guard = 0; // prevent infinity loop $space = array($this->copy_skip($this->token_blank), '', ''); // attributes do { if ($this->char!==null && $space[0]==='') break; $name = $this->copy_until($this->token_equal); if($guard===$this->pos) { $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next continue; } $guard = $this->pos; // handle endless '<' if($this->pos>=$this->size-1 && $this->char!=='>') { $node->nodetype = HDOM_TYPE_TEXT; $node->_[HDOM_INFO_END] = 0; $node->_[HDOM_INFO_TEXT] = '<'.$tag . $space[0] . $name; $node->tag = 'text'; $this->link_nodes($node, false); return true; } // handle mismatch '<' if($this->doc[$this->pos-1]=='<') { parse attributes protected function parse_attr($node, $name, &$space) { $space[2] = $this->copy_skip($this->token_blank); switch($this->char) { case '"': $node->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_DOUBLE; $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next $node->attr[$name] = $this->restore_noise($this->copy_until_char_escape('"')); $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next break; case '\'': $node->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_SINGLE; $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next $node->attr[$name] = $this->restore_noise($this->copy_until_char_escape('\'')); $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next break; default: $node->_[HDOM_INFO_sor; $node->_[HDOM_INFO_TEXT] = ''; $this->link_nodes($node, false); $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next return true; } protected function skip($chars) { $this->pos += strspn($this->doc, $chars, $this->pos); $this->char = ($this->pos<$this->size) ? $this->doc[$this->pos] : null; // next } protected function copy_skip($chars) { $pos = $this->pos; $len = strspn($this->doc, $chars, $pos); $this->pos += $len; $this->char = ($this->pos<$this->size) ? $this->doc[$this->pos] : null; // next if ($len===0) return ''; return substr($this->doc, $pos, $len); } protected function copy_until($chars) { $pos = $this->pos; $len = strcspn($this->doc, $chars, $pos); $this->pos += $len; $this->char = ($this->pos<$this->size) ? $this->doc[$this->pos] : null; // next return substr($this->doc, $pos, $len); } protected function copy_until_char($char) { if ($this->char===null) return ''; if (($pos = strpos($this->doc, $char, $this->pos))===false) { $ret = substr($this->doc, $this->pos, $this->size-$this->pos); $this->char = null; $this->pos = $this->size; return $ret; } if ($pos===$this->pos) return ''; $pos_old = $this->pos; $this->char = $this->doc[$pos]; $this->pos = $pos; return substr($this if ($this->doc[$pos-1]==='\\') { $start = $pos+1; continue; } $pos_old = $this->pos; $this->char = $this->doc[$pos]; $this->pos = $pos; return substr($this->doc, $pos_old, $pos-$pos_old); } } // remove noise from html content protected function remove_noise($pattern, $remove_tag=false) { $count = preg_match_all($pattern, $this->doc, $matches, PREG_SET_ORDER|PREG_OFFSET_CAPTURE); for ($i=$count-1; $i>-1; --$i) { $key = '___noise___'.sprintf('% 3d', count($this->noise)+100); $idx = ($remove_tag) ? 0 : 1; $this->noise[$key] = $matches[$i][$idx][0]; $this->doc = substr_replace($this->doc, $key, $matches[$i][$idx][1], strlen($matches[$i][$idx][0])); } // reset the length of content $this->size = strlen($this->doc); if ($this->size>0) $this->char = $this->doc[0]; } // restore noise to html con The Learning Teacher Network | The Learning Teacher Network

Contact

Contact us to learn more!

Learning Teacher Network Conference and Plans for 2017-2018

The announcement of the Executive Committee for the members and partners of the Learning Teacher Network

Conferences

There is always a joy in learning and networking. Take part in the network’s conferences to gain new knowledge and experience, and to enjoy learning...

UNESCO

The Learning Teacher Network is a UNESCO Key Partner in the Global Action Programme on Education for Sustainable Development

The Learning Teacher Network

Share...

UNESCO

The Learning Teacher Network is a UNESCO Key Partner in the Global Action Programme on Education for Sustainable Development

Learning Teacher Network Conference and Plans for 2017-2018

The announcement of the Executive Committee for the members and partners of the Learning Teacher Network

Our publications

The Learning Teacher Network promotes education and training on all levels in various ways - through conferences, networking, forums and pub...

Conferences

There is always a joy in learning and networking. Take part in the network’s conferences to gain new knowledge and experience, and to enjoy...