0, 'end' => 0, 'inner_begin' => 0, 'inner_end' => 0, 'tag_end' => 0 ); public function __construct($_source, $_pos_diff = 0, $_main = false) { if ($_pos_diff === true) { $_main = true; $_pos_diff = 0; } if ($_main) { if (stripos($_source, ']+(>)]is', $_source, $m, PREG_OFFSET_CAPTURE)) { $_source = substr_replace($_source, '', $m[1][1] + 1, 0); } } if (stripos($_source, 'doc = $_source; } $this->pos_diff = $_pos_diff; $this->parse_self($_source, $_main); if ($_main) $this->parse_all(); } public function __set($_attr, $_value) { $this->set_attribute($_attr, $_value); } public function __get($_attr) { if ($_attr == 'innerHTML') { $length = $this->pos['inner_end'] - $this->pos['inner_begin']; return substr($this->doc, $this->pos['inner_begin'], $length); } elseif ($_attr == 'tagName') { $begin = $this->pos['begin'] + 1; $length = $this->pos['tag_end'] - $begin; return substr($this->doc, $begin, $length); } else { $attr = $this->parse_attributes(); return (array_key_exists($_attr, $attr)) ? $attr[$_attr] : false; } } private function parse_self($_source, $_main = false) { $pattern = ($_main) ? '[<(html)' : '[<(\w+\d?)'; $pattern .= '([^>]*)>(.*)]is'; preg_match($pattern, $_source, $matches, PREG_OFFSET_CAPTURE); for ($i = 0; $i < count($matches); $i++) $matches[$i][2] = $matches[$i][1] + strlen($matches[$i][0]); $this->pos['begin'] = $matches[0][1]; $this->pos['end'] = $matches[0][2]; $this->pos['inner_begin'] = $matches[3][1]; $this->pos['inner_end'] = $matches[3][2]; $this->pos['tag_end'] = $matches[1][2]; foreach ($this->pos as &$pos) { $pos += $this->pos_diff; } } private function parse_attributes() { $attr_length = $this->pos['inner_begin'] - $this->pos['tag_end'] - 1; $attr_string = substr($this->doc, $this->pos['tag_end'], $attr_length); $attributes = array(); $pattern = '[(\w+)(?:=(\'|")(.*?)\\2)?]is'; preg_match_all($pattern, $attr_string, $m, PREG_SET_ORDER); for ($i = 0; $i < count($m); $i++) { $attributes[$m[$i][1]] = (isset($m[$i][2])) ? $m[$i][3] : true; } return $attributes; } private function generate_attributes($_array) { $attributes = ''; ksort($_array); foreach ($_array as $attr => $value) { if ($value !== false) $attributes .= ($value === true) ? ' ' . $attr : " $attr=\"$value\""; } return $attributes; } private function set_attribute($_attr, $_value) { $old_length = $this->pos['inner_begin'] - $this->pos['tag_end'] - 1; $attributes = $this->parse_attributes(); $attributes[$_attr] = $_value; $attributes = $this->generate_attributes($attributes); $new_length = strlen($attributes); $this->doc = substr_replace($this->doc, $attributes, $this->pos['tag_end'], $old_length); $pos_diff = $new_length - $old_length; $this->update_elements($pos_diff); $this->pos['inner_begin'] += $pos_diff; $this->pos['inner_end'] += $pos_diff; $this->pos['end'] += $pos_diff; } private function update_elements($_pos_diff) { foreach ($this->elements as &$e) { if ($e != $this) foreach ($e->pos as &$pos) { if ($pos >= $this->pos['inner_begin']) $pos += $_pos_diff; } } } private function parse_all() { $pattern = "[(?<=<)/?\w+\d?(?=[^>]*>)]is"; preg_match_all($pattern, $this->innerHTML, $m, PREG_OFFSET_CAPTURE); $m = $m[0]; $key = 0; for ($i = 0; $i < count($m); $i++) { $found = false; $skip = 1; if (strpos($m[$i][0], '/') === false) { for ($j = $i + 1; $j < count($m); $j++) { if ($m[$j][0] == '/' . $m[$i][0]) { $skip--; } elseif ($m[$j][0] == $m[$i][0]) { $skip++; } if ($skip <= 0) { $tag_start = $m[$i][1] - 1; $tag_length = $m[$j][1] - 1 - $tag_start + strlen($m[$j][0]) + 2; $source = substr($this->innerHTML, $tag_start, $tag_length) . "\n\n"; $class_name = get_class($this); $this->elements[$key] = new $class_name($source, $tag_start + $this->pos['inner_begin']); $key++; break; } } } } foreach ($this->elements as &$element) { $element->doc = &$this->doc; $element->elements = &$this->elements; } } public function &getElementById($_id) { foreach ($this->elements as &$e) { if ($e->id == $_id) { return $e; break; } } return null; } public function &getElementsByTagName($_tag) { $elements = array(); foreach ($this->elements as &$e) { if (strtolower($e->tagName) == strtolower($_tag)) { $elements[] = &$e; } } return $elements; } public function &getElementsByAttribute($_attr) { $elements = array(); foreach ($this->elements as &$e) { if ($e->$_attr !== false) $elements[] = &$e; } return $elements; } } ?>