| 
 Парсинг HTML -> DOM в нормальных браузерах (таки проблема) Господа, пишу библиотеку по работе с DOM (для новых браузеров) и столкнулся с проблемой парсинга html. Конечная цель - сделать максимально компактно (< 1K). Это очередной мой опен соурц проект, о котором будет рассказано на Хабре и здесь. К сожалению, я не могу найти простого решения парсинга HTML и представления его в виде DOM. Что первое приходит в голову? Создание элемента (дива) и вставка в него html. div = document.createElement( 'div' ); div.innerHTML = '<p>a<p>b'; alert( div.innerHTML ); myDomNodes = div.children; Проблема возникает, когда нам нужно распарсить элемент таблицы. div = document.createElement( 'div' ); div.innerHTML = '<tr>a</tr><tr>b</tr>'; alert( div.innerHTML ); Понятно, почему так происходит: tr, td, tbody, thead, tfoot... не могут находиться внутри элементов, не являющихся их родителями по спецификации. Другой вариант: использовать DOMParser var doc = new DOMParser().parseFromString( '<tr>a</tr><tr>b</tr>', "text/html"); alert( doc.body.innerHTML ); Та же проблема. Пробуем поменять контент-тайп на xml (потмо можно "усыновить" ноды методом document.adoptNode): var doc = new DOMParser().parseFromString( '<tr>a</tr><tr>b</tr>', "application/xml"); console.log( doc ); Не ок. Метод будет парсить любой код выше (<tr>a</tr><tr>b</tr>, <p>a<p>b) с ошибками (не закрытый тег, который по стандарту html и не требуется закрывать, отсутствия рут элемента....) Значит и этот метод нам не подходит. А что по поводу DocumentFragment? Ничего. У него нет свойства innerHTML. Печаль. Как это делается в библиотеках? http://habrahabr.ru/post/164533/ Но предварительно jQuery пытается найти, не нужно ли обрамить наш код как-то дополнительно. Берется самый первый найденный в коде тег и ищется в служебном объекте wrapMap. В Библиотеках это делается через, простите, жопу. На дворе 2014 год и нет ни одного способа распарсить HTML в последнем хроме и файерфоксе? Не верю. | 
| 
 Цитата: 
 Цитата: 
 Цитата: 
 А вот то что DOMParser не умеет парсить фрагменты - это недочет, как мне кажется. | 
| 
 Все-таки хотел узнать за каким парсить хтмл вообще? Ну я понимаю читеркод, когда исходник не твой и надо ковырять чужой моск. Но если он твой, то какой может быть задача пихать еду через задницу? | 
| 
 Цитата: 
 | 
| 
 Цитата: 
 Это XML можно разобрать в отрыве от контекста. С HTML это не прокатит. Например если HTML-парсер встретит тег <td> разбирая содержимое div'а, то он проигнорирует этот тег и вставит только его содержимое. А если это произойдет в контексте <table>, <tbody> или <tr> то он его не проигнорирует, да к тому же создаст недостающие части таблицы (tbody, tr). То есть HTML парсер имеет кучу состояний, зависящих от контекста. Теперь понимаешь почему у DocumentFragment нет innerHTML? Ах да, в разных контекстах не только разное поведение при встрече тегов, но даже в некоторых контекстах теги могут вобще распознаваться как текст. Это касается контекстов <title>, <noscript>, <plaintext>, <textarea> и тд. Внутри <script> вообще особое поведение - в нем распознается только закрывающий тег </script> Матчасть: http://www.whatwg.org/specs/web-apps...sing-algorithm | 
| 
 Цитата: 
 | 
| 
 Цитата: 
 Ваша аргументация мне понятна. Описание поведения в таких случаях описано в спецификации. И моё недовольство касается не реализации чего-либо в браузерах, а документального описания реализации в спецификации. Цитата: 
 Ну да ладно, ответа на мой вопрос нет и, судя по всему не будет. А спорить мы можем долго. | 
| 
 Цитата: 
 Цитата: 
 Цитата: 
 И наверное если подумать, то всплывут ситуации, где нельзя "догадаться" о контексте. | 
| 
 danik.js, вы, как и в предыдущих сообщениях защищаете спецификацию. Моя точка зрения: спецификаторы должны были до 2014 (!) года предусмотреть безконтекстный парсер. Повторюсь. Цитата: 
 Цитата: 
 Цитата: 
 | 
| 
 Написал простейшее решение. Проверяется только первый тег в строке, для остальных контекст остается тем же, что и для первого. 
window.parseHTML = function( html ) {
	var node = document.createElement( 'div' ),
		// wrapMap is taken from jQuery
		wrapMap = {
				option: [ 1, "<select multiple='multiple'>", "</select>" ],
				legend: [ 1, "<fieldset>", "</fieldset>" ],
				thead: [ 1, "<table>", "</table>" ],
				tr: [ 2, "<table><tbody>", "</tbody></table>" ],
				td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
				col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
				area: [ 1, "<map>", "</map>" ],
				_default: [ 0, "", "" ]
		},
		wrapper,
		i;
	
	wrapMap.optgroup = wrapMap.option;
	wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
	wrapMap.th = wrapMap.td;
	
	wrapper = wrapMap[ /<([\w:]+)/.exec( html )[ 1 ] ] || wrapMap._default;
	
	node.innerHTML = wrapper[ 1 ] + html + wrapper[ 2 ];
	
	i = wrapper[ 0 ];
	while( i-- ) {
		node = node.firstElementChild;
	}
	
	return node.children;
};
 | 
| Часовой пояс GMT +3, время: 05:46. |