Показаны сообщения с ярлыком HTML. Показать все сообщения
Показаны сообщения с ярлыком HTML. Показать все сообщения
четверг, 13 января 2011 г.
Как называются радиобатоны по-русски?
Не задумывался над этим, спросили, откопал вот такие варианты -
"Радио",
"Переключатель",
"Переключатель многопозиционый" ))
но все таки правильный - "Радиокнопка"
понедельник, 27 декабря 2010 г.
Парсер простого HTML
Убирает не закрыте, не нужные теги и атрибуты. Выводит отчет.
Выводит:
Скопипаситл с пыхи
Код - пример #1 | |
1 |
<?php error_reporting(-1); class MyHtmlTidy { const TAG = '<(?:"[^"]*"|\'[^\']*\'|[^\'">])*>', ATTR = '\w++\s*=\s*"[^"]++"|\w++\s*=\s*\'[^\']++\'|\w++\s*=\s*[^\s]++'; private $_goodTags = array('b', 'i', 'u', 's', 'p', 'a', 'img', 'br', 'hr'), $_selfClose = array('img', 'br', 'hr'), $_goodAttrs = array( 'a' => array('href', 'title'), 'img' => array('src', 'alt')), $_nest = array(); public $errors = array(); public function preparse($html) { $this->_nest = array(); $this->errors = array(); $text = preg_replace_callback('/('.self::TAG.')/Uus', array($this, '_replace'), $html); if (!empty($this->_nest)) { $this->errors[] = 'Unclosed tags ' . implode(', ', $this->_nest); $text .= '</' . implode('></', array_reverse($this->_nest)) . '>'; } return $text; } private function _replace($matches) { $tag = $matches[1]; preg_match('/^<\/?(\w++)/', $tag, $m); $tagName = strtolower($m[1]); $isSelfClosed = $tag{strlen($tag) - 2} == '/'; $attrs = trim(substr($tag, strlen($m[0]), ($isSelfClosed ? -2 : -1))); if (!in_array($tagName, $this->_goodTags)) { $this->errors[] = 'Tag ' . $tagName . ' is deprecated'; return ''; } // Closing tag if ($tag{1} == '/') { if (empty($this->_nest) || end($this->_nest) != $tagName) { $this->errors[] = 'Odd close tag ' . $tagName; return '<' . $tagName . '></' . $tagName . '>'; } array_pop($this->_nest); return '</' . $tagName . '>'; } // Open tag or self-closing tag $isSelfClosed = $isSelfClosed || in_array($tagName, $this->_selfClose); if (!$isSelfClosed) { $this->_nest[] = $tagName; } if (!isset($this->_goodAttrs[$tagName])) { // No attributes at all if (strlen($attrs)) { $this->errors[] = 'Tag ' . $tagName . ' cannot have attributes'; } $attrs = ''; } else { // Check every attribute preg_match_all('/'.self::ATTR.'/Uus', $attrs, $m); $attrs = $m[0]; foreach ($attrs as $i => $attr) { $p = strpos($attr, '='); $attrName = strtolower(trim(substr($attr, 0, $p))); if (!in_array($attrName, $this->_goodAttrs[$tagName])) { $this->errors[] = 'Wrong ' . $tagName . ' attribute ' . $attrName; unset($attrs[$i]); } else { $attrs[$i] = $attrName . '=' . trim(substr($attr, $p + 1)); } } $attrs = count($attrs) ? (' ' . implode(' ', $attrs)) : ''; } return '<' . $tagName . $attrs . ($isSelfClosed ? '/>' : '>'); } } $t = new MyHtmlTidy(); $html = <<<HTML <p class='blabla'>dslkldsldslsd<br> kjksdjsdk<a href="http://thesite.name/path" target="_new" title="ololo" onclick="javascript:doit('xxx')">djdkjdk</a> <img src=0.gif alt='pysh-pysh'> ds;lsd;; <b>skjskjsk kjdkjdkd HTML; header('Content-type: text/plain'); echo $html; echo "\n===========================\n"; $preparsed = $t->preparse($html); if (!empty($t->errors)) { echo implode("\n", $t->errors); echo "\n===========================\n"; } echo $preparsed; |
Код - пример #1 |
<p class='blabla'>dslkldsldslsd<br> kjksdjsdk<a href="http://thesite.name/path" target="_new" title="ololo" onclick="javascript:doit('xxx')">djdkjdk</a> <img src=0.gif alt='pysh-pysh'> ds;lsd;; <b>skjskjsk kjdkjdkd =========================== Tag p cannot have attributes Wrong a attribute target Wrong a attribute onclick Unclosed tags p, b =========================== <p>dslkldsldslsd<br/> kjksdjsdk<a href="http://thesite.name/path" title="ololo">djdkjdk</a> <img src=0.gif alt='pysh-pysh'/> ds;lsd;; <b>skjskjsk kjdkjdkd</b></p> |
среда, 15 декабря 2010 г.
Удобный класс для парсинга HTML на PHP
Сам класс с примерами работы:
Ошибки html игнорируются.
Распознаются вложеные теги (через пробел), а также конструкции вида .class, #id и [attr=value]
Создание из строки: nokogiri::fromString($htmlString); или new nokogiri($htmlString);
Создание из DomDocument: nokogiri::fromDom($dom);
Требования:
DOM, libxml, php 5.3 (вероятно работает и со многими старыми версиями)
HTML на входе должен быть в кодировке UTF-8
Предыдущие версии можно найти здесь.
Скопипастил с хабра
Код - пример #1 | |
1 |
<?php $html = gzdecode(file_get_contents('http://habrahabr.ru/')); $saw = new nokogiri($html); var_dump($saw->get('a.habracut')->toArray()); /* На выходе: Array(6) { [0]=> array(3) { ["class"]=> string(8) "habracut" ["href"]=> string(56) "http://habrahabr.ru/blogs/google_chrome/110099/#habracut" ["#text"]=> string(29) "Читать дальше >" } [1]=> .... */ var_dump($saw->get('ul.panel-nav-top li.current')->toArray()); /* На выходе: array(2) { ["class"]=> string(7) "current" ["a"]=> array(3) { ["href"]=> string(20) "http://habrahabr.ru/" ["class"]=> string(8) "disabled" ["#text"]=> string(10) "Посты" } } */ var_dump($saw->get('#sidebar dl.air-comment a.topic')->toArray()); /* На выходе: array(50) { [0]=> array(3) { ["class"]=> string(5) "topic" ["href"]=> string(36) "http://habrahabr.ru/blogs/os/110045/" ["#text"]=> string(63) "ФБР внедряло backdoor'ы в IPSec код OpenBSD (?)" } [1]=> array(3) { ["cl */ var_dump($saw->get('a[rel=bookmark]')->toArray()); /* На выходе: array(10) { [0]=> array(4) { ["rel"]=> string(8) "bookmark" ["href"]=> string(47) "http://habrahabr.ru/blogs/google_chrome/110099/" ["class"]=> string(5) "topic" ["#text"]=> string(100) "Google объявил Chrome готовым..." } [1]=> array(4) { ["rel"]= */ /** * Description of nokogiri * * @author olamedia */ class nokogiri implements IteratorAggregate{ protected $_source = ''; /** * @var DOMDocument */ protected $_dom = null; /** * @var DOMXpath * */ protected $_xpath = null; public function __construct($htmlString = ''){ $this->loadHtml($htmlString); } public static function fromHtml($htmlString){ $me = new self(); $me->loadHtml($htmlString); return $me; } public static function fromDom($dom){ $me = new self(); $me->loadDom($dom); return $me; } public function loadDom($dom){ $this->_dom = $dom; $this->_xpath = new DOMXpath($this->_dom); } public function loadHtml($htmlString = ''){ $dom = new DOMDocument('1.0', 'UTF-8'); $dom->preserveWhiteSpace = false; if (strlen($htmlString)){ libxml_use_internal_errors(TRUE); $dom->loadHTML($htmlString); libxml_clear_errors(); } $this->loadDom($dom); } function __invoke($expression){ return $this->get($expression); } public function get($expression){ if (strpos($expression, ' ') !== false){ $a = explode(' ', $expression); foreach ($a as $k => $sub){ $a[$k] = $this->getXpathSubquery($sub); } return $this->getElements(implode('', $a)); } return $this->getElements($this->getXpathSubquery($expression)); } protected function getXpathSubquery($expression){ $query = ''; if (preg_match("/(?P<tag>[a-z0-9]+)? (\[(?P<attr>\S+)=(?P<value>\S+)\])? (#(?P<id>\S+))? (\.(?P<class>\S+))?/ims", $expression, $subs)){ $tag = $subs['tag']; $id = $subs['id']; $attr = $subs['attr']; $attrValue = $subs['value']; $class = $subs['class']; if (!strlen($tag)) $tag = '*'; $query = '//'.$tag; if (strlen($id)){ $query .= "[@id='".$id."']"; } if (strlen($attr)){ $query .= "[@".$attr."='".$attrValue."']"; } if (strlen($class)){ //$query .= "[@class='".$class."']"; $query .= '[contains(concat(" ", normalize-space(@class), " "), " '.$class.' ")]'; } } return $query; } protected function getElements($xpathQuery){ $newDom = new DOMDocument('1.0', 'UTF-8'); $root = $newDom->createElement('root'); $newDom->appendChild($root); if (strlen($xpathQuery)){ $nodeList = $this->_xpath->query($xpathQuery); if ($nodeList === false){ throw new Exception('Malformed xpath'); } foreach ($nodeList as $domElement){ $domNode = $newDom->importNode($domElement, true); $root->appendChild($domNode); } return self::fromDom($newDom); } } public function toXml(){ return $this->_dom->saveXML(); } public function toArray($xnode = null){ $array = array(); if ($xnode === null){ $node = $this->_dom; }else{ $node = $xnode; } if ($node->nodeType == XML_TEXT_NODE){ return $node->nodeValue; } if ($node->hasAttributes()){ foreach ($node->attributes as $attr){ $array[$attr->nodeName] = $attr->nodeValue; } } if ($node->hasChildNodes()){ if ($node->childNodes->length == 1){ $array[$node->firstChild->nodeName] = $this->toArray($node->firstChild); }else{ foreach ($node->childNodes as $childNode){ if ($childNode->nodeType != XML_TEXT_NODE){ $array[$childNode->nodeName][] = $this->toArray($childNode); } } } } if ($xnode === null){ return reset(reset($array)); // first child } return $array; } public function getIterator(){ $a = $this->toArray(); return new ArrayIterator($a); } } |
Распознаются вложеные теги (через пробел), а также конструкции вида .class, #id и [attr=value]
Создание из строки: nokogiri::fromString($htmlString); или new nokogiri($htmlString);
Создание из DomDocument: nokogiri::fromDom($dom);
Требования:
DOM, libxml, php 5.3 (вероятно работает и со многими старыми версиями)
HTML на входе должен быть в кодировке UTF-8
Код - пример #1 | |
1 |
foreach ($saw->get('#sidebar a.topic') as $link){ var_dump($link['#text']); } |
понедельник, 13 декабря 2010 г.
Функция закрытия незакрытых тегов в HTML
Код - пример #1 | |
1 |
/** * close all open xhtml tags at the end of the string * * @param string $html * @return string * @author Milian Wolff <mail@milianw.de> */ function closetags($html) { #put all opened tags into an array preg_match_all('#<([a-z]+)(?: .*)?(?<![/|/ ])>#iU', $html, $result); $openedtags = $result[1]; #put all closed tags into an array preg_match_all('#</([a-z]+)>#iU', $html, $result); $closedtags = $result[1]; $len_opened = count($openedtags); # all tags are closed if (count($closedtags) == $len_opened) { return $html; } $openedtags = array_reverse($openedtags); # close tags for ($i=0; $i < $len_opened; $i++) { if (!in_array($openedtags[$i], $closedtags)){ $html .= '</'.$openedtags[$i].'>'; } else { unset($closedtags[array_search($openedtags[$i], $closedtags)]); } } return $html; } |
Подписаться на:
Сообщения (Atom)