SSI сайт: HTML, XML, XSLT

в 9:15, , рубрики: SSI, XML, xslt, ненормальное программирование

image

Достопочтенное Ретро! Благо ты или зло?
Вздохом какого ветра к нам тебя занесло?
© Роберт Рождественский

Есть вещи, которые просто нравятся, их приятно держать в руках, они просты, они понятны. Время их расцвета ушло, но сами они не канули в лету, и к ним возвращаются снова и снова. Это касается не только предметов материального мира. Всегда найдётся программист, которому интересно писать на ассемблере, или прямо в машинных кодах, любитель простоты, минимализма, ретро. Попробуем вернуться к SSI, благо, это и проще ассемблера, и значительно моложе.

Технология SSI в своё время позволяла (и сейчас позволяет), делать сайты, в которых часть контента выносилась в отдельный файл, включаемый сервером «на лету». Обычно в отдельные файлы выносились: хидер, сайдбар, футер. Для обычного сайта с простой структурой этого хватало с лихвой. Выигрыш же состоял в том, что использовались простые, быстрые и надёжные решения, которые фактически без программирования реализовывали функционал CMS. Да и вообще, минимальный стек технологий — это любопытно.

Типичная страница сайта «на инклудах» выглядела так:

<html>
<head>
	<title>Название страницы</title>
</head>
<body>
	<div id="header"><?php include ("header.php");?></div>
	<div id="sidebar"><?php include ("sidebar.php");?></div>
	<div id="footer"><?php include ("footer.php");?></div>
</body>
</html>

Но работа с множеством страничек вызывала некоторое неудобство. Появились CMS, которые снимали одни вопросы, и ставили другие. Интересным решением было хранение базы данных в виде одного html файла, в котором страницы обозначались тегами Н1, Н2, Н3. При этом цифра тега говорила в вложенности страницы. Идею эту я наблюдал в CMSimple cmsimple.org, хотя возможно, кто-то это придумал и ранее. На базе этой идеи наверняка создано достаточно много CMS (да и сам пробовал, каюсь, чего уж там).

Главный недостаток такого решения — необходимость ворочать большой html файл. Есть конечно возможность сделать индекс, но по большому счёту это уже не так интересно. Одно дело редактировать десяток статей в одном файле, другое — тысячи. Примем как данность, что такой движок уместен для небольшого сайта, и не важно, СДЛ это, или сателлит — мы ведь обсуждаем технологию.

SSI и БД в HTML

Что за изгибы моды? Время сошло с ума:
Бабушкины комоды в блочные лезут дома!

Вспомнив о SSI, я задался вопросом: а нельзя ли подобный подход реализовать с помощью этой технологии? Сказано — сделано. Прямо в html файле можно создать переменную, значением которой и будет база данных сайта:

<!--#set var="db" value="Your html db">

Осталось научиться делать выборку из этой базы данных. Для этого пригодится переменная QUERY_STRING, которая хранит строку запроса к сайту. Настроив реврайты в htaccess и используя возможность условных выражений с поддержкой регулярных выражений (сорри за тавтологию), сервер сможет делать выборку нужной статьи из базы.

К сожалению, в SSI нет циклов, поэтому перебрать базу данных и сформировать сайдбар со списком страниц не получится: его придётся делать вручную. Неудобно, но это ограничения SSI. Также мне сильно не хватило возможности поместить в переменную содержание сайта, чего-то такого:

<!--#set var="db" file="db.html">

Такая опция позволила бы базу данных поместить в отдельный файл, соответственно код «движка» был бы более чистым и читаемым. Так что «лапша-код», это наше всё.

Для эксперимента решил сделать простой сайт, чтобы попробовать в деле предлагаемое решение. Темой выбран латино-американский танец Румба (исходники ниже). Первое впечатление — сайт работает быстро. Поскольку размер «движка» вместе с базой данных чуть больше 10 килобайт, это не удивительно. Запишем это в плюс. Плюс этот будет оставаться таковым до тех пор, пока размер БД не вырастет к примеру до мегабайта. При этом необходимость формирования меню вручную остановит от ваяния большого сайта гораздо раньше. Кроме того, копипастя что-либо в БД, необходимо не забывать заменять двойные кавычки на одинарные.

Ничего необычного и сложного. Вполне возможное решение. Важно, что странички благодаря реврайтам поисковые системы будут индексировать как отдельные, а не как одну целую. Этим конечно никого не удивишь, но упомянуть не помешает. Также в плюс запишем малую нагрузку на сервер. Не самый важный фактор для маленького сайта, но пусть будет. Если есть желание прикрутить дескрипшены — это также не проблема, достаточно ввести ещё один тег в состав разметки записей-статей.

Эти файлы нужно создать на сайте, чтобы увидеть пример в действии:

.htaccess

AddDefaultCharset utf-8

AddType text/html .html
AddHandler server-parsed .html
DirectoryIndex rumba.shtml?query=start

RewriteEngine on
RewriteRule ^([a-zA-Z0-9-]+).html$ rumba.shtml?query=$1

rumba.shtml

	<!--#set var="rumba_title" value="" -->
	<!--#set var="rumba_content" value="" -->
	<!--#set var="rumba_menu" value="" -->
	<!--#set var="rumba_error_title" value="Страница не найдена" -->
	<!--#set var="rumba_error_text" value="<h2>404</h2>Страница не найдена" -->	
	
	<!--#set var="rumba_menu" value="<ul>
		<li><a href='./'>Главная</a></li>
		<li><a href='./history.html'>История румбы</a></li>
		<li><a href='./cha-cha-cha.html'>Румба и Ча-ча-ча</a></li>
		<li><a href='./types.html'>Виды румбы</a></li>
		<li><a href='./emotion.html'>Эмоциональное содержание танца</a></li>
		<li><a href='./hits.html'>Хиты румбы</a></li>
	</ul>" -->

	<!--#set var="rumba_db" value="<articles>
		<article id='start'>
			<h2>Румба — парный кубинский танец африканского происхождения</h2>
			<text>
				<a href='https://ru.wikipedia.org/wiki/Румба'>Ру́мба</a> (исп. rumba) — у этого слова есть два различных значения:
				<ol>
				<li>Одно из них относится к направлению танцев и музыке, родившихся на Кубе. Наиболее известным из них является rumba Guaguanco. Так же популярными являются rumba Yambu и rumba Columbia. Каждый из этих видов румбы имеет свою стилистику музыки и танцевания, но в целом они очень близки.</li>
				<li>Другое значение появилось сравнительно недавно и относится к танцу из программы бальных танцев, который входит в программу соревнований. В этом значении румба является самым медленным из пяти танцев соревновательной латино-американской программы (остальные четыре — пасодобль, самба, ча-ча-ча и джайв). Танец и музыка румбы из соревновательной программы латино-американских танцев происходят от кубинских музыкальных стилей и танцев болеро и сон.</li>
				</ol>
			</text>
		</article>
		<article id='history'>
			<h2>История румбы</h2>
			<text>
				Румба появилась в Гаване в 19-м веке в комбинации с европейским контрдансом. Название «Rumba», возможно, происходит от названия танцевальных групп в 1807 году — «rumboso orquestra», хотя в Испании слово «rumbo» означает «путь» (в русском морской аналог — «румбы», то есть направление). Замечание - российская морская терминология аккуратно заимствована у Нидерландов, поэтому 'направление' очевидно не в русском, а в голландском не так.
			</text>
		</article>
		<article id='cha-cha-cha'>
			<h2>Румба и Ча-ча-ча</h2>
			<text>
				<p>Изначально не существовало четкого разделения танцев румба дансона и ча-ча-ча, из-за чего вся музыка, характерным образом обыгрывавшая первую долю (несколько ударов из затакта, приводящих к первой доле), подпадала под категорию румбы. Со временем танцы четко разделились. Музыка румбы дансона приобрела более медленный темп, стала сочиняться, как правило, в минорном ладу, и приобрела свое обыгрывание первой доли (ударные: восьмая, восьмая, восьмая, четверть — первая доля). Музыка ча-ча-ча стала быстрее, сочиняется как в мажорном, так и в минорном ладу и имеет собственное, очень выраженное и подчеркнутое обыгрывание первой доли (восьмая, восьмая, четверть — первая доля, так называемое — «ча-ча-ча» или «ча-ча-раз»).</p>
				<p>В связи с этим многие знаменитые в прошлом румбы с современной точки зрения следует считать скорее ча-ча-ча или даже вообще невозможно четко классифицировать как один из этих танцев. Так, например, знаменитая мелодия «Кукарача», считавшаяся румбой, не является ни ею, ни ча-ча-ча с современной точки зрения. «Guantanamera» более известна в варианте ча-ча-ча, а не румбы.</p>
				<p>Таким образом, румба обязана своим рождением религиозным ритуалам, развивалась она на базе ярко выраженных ритмов и хоровых голосов. Также можно сказать, что румбой в какой-то степени являются все те танцы, которые были созданы кубинцами. В настоящее время этот танец известен на всех континентах. Сначала он пришел в кабаре, а затем на телевидение. Существует бальная румба, но она существенно отличается от аутентичного кубинского варианта.</p>
			</text>
		</article>
		<article id='types'>
			<h2>Виды румбы</h2>
			<text>
				<p>В начале XIX века на Кубе существовало три варианта румбы, но широкую известность получила румба Гуагуанко (Guaguanco), танец, во время которого кавалер следует за дамой в поисках соприкосновения бедрами, а дама старается этого избежать. В этом танце дама как бы является объектом дерзкого ухаживания и старается сдержать страсть своего партнера. Возможно из-за этого за румбой и закрепилось название - «танец любви».</p>
				<p>Так-же на Кубе существовали различные виды румбы, которые танцевались на праздниках и просто сборищах людей на улице. Ярким представителем является Румба Миметика, в которой изображаются различные сцены из жизни простых людей (Papilote, Mama'buela, Gavilan)</p>
				<p>Коренную эволюцию румба претерпела, будучи вывезенной в США. Наравне с экспансивной, эротичной кубинской появилась Румба американская – с более сдержанными движениями и стилем. Именно этот вариант румбы и распространился по всему миру, завоевав сердца нескольких поколений танцоров и просто ценителей латиноамериканской культуры. Гуагуанко в основном состоит из ритмов африканских барабанов, которые накладываются на ритм клавэ (clave), представляющий смещенный акцент, известный как 3-2. Пение без музыкального сопровождение напоминает старинные испанские мелодии, которые накладываются на ритмы африканских барабанов. Исполняется гуагуанко одним или несколькими солистами, тему и слова придумывают по ходу исполнения песни. Структура ритма гуагуанко основывается чаще всего на ритме румбы сон (Rumba Son).</p>
			</text>
		</article>
		<article id='emotion'>
			<h2>Эмоциональное содержание танца</h2>
			<text>
				Среди всех бальных танцев румба характеризуется наиболее глубоким эмоциональным содержанием. В ходе своей эволюции румба приобрела многие черты, характерные для блюза. Существует расхожий штамп, что «румба — танец любви». Контраст ярко выраженного эротического характера танца и драматического содержания музыки создаёт неповторимый эстетический эффект. Вопреки всеобщему мнению о том, что движения в румбе — это танцевальное воплощение эротических чувств, румба изначально была свадебным танцем, а ее движения обозначали не что иное как семейные обязанности супругов. Немногочисленные современные румбы, написанные в мажоре, имеют свою изюминку, но не оставляют такого глубокого впечатления.
			</text>
		</article>
		<article id='hits'>
			<h2>Хиты написанные в ритме румбы</h2>
			<text>
				<ul>
				<li>La Media Vuelta — Эйди Горме (Eydie Gorme)</li>
				<li>Manana</li>
				<li>Cantinero de Cuba</li>
				<li>Reflection — Кристина Агилера</li>
				<li>Fairy tale — Тони Брэкстон</li>
				<li>Don't Know Why — Нора Джонс</li>
				<li>Falling Into You — Celine Dion</li>
				<li>When the blue bird sings</li>
				<li>Gipsy Kings — La Rumba-De Nicolas</li>
				<li>Gipsy Kings — Una Rumba Por Aqui</li>
				<li>Gipsy Kings — Rumba Del Stud</li>
				</ul>
			</text>
		</article>
	</articles>" -->

	<!--#if expr="$QUERY_STRING = /^query=([a-zA-Z0-9-]+)/" -->
		<!--#set var="rumba_query" value="$1" -->
		<!--#if expr="${rumba_db} = /<article id='${rumba_query}'>[\s\S]*?<h2>(.*)</h2>[\s\S]*?<text>([\s\S]*?)</text>[\s\S]*?</article>/" -->
			<!--#set var="rumba_title" value="$1" -->
			<!--#set var="rumba_r1" value="$1" -->
			<!--#set var="rumba_r2" value="$2" -->
			<!--#set var="rumba_content" value="${rumba_content}<h2>${rumba_r1}</h2>${rumba_r2}" -->
		<!--#else -->
			<!--#set var="rumba_title" value="${rumba_error_title}" -->
			<!--#set var="rumba_content" value="${rumba_error_text}" -->
		<!--#endif -->
	<!--#else -->
			<!--#set var="rumba_title" value="${rumba_error_title}" -->
			<!--#set var="rumba_content" value="${rumba_error_text}2" -->
	<!--#endif -->
	
<html>
<head>
	<title><!--#echo encoding="none" var="rumba_title" --></title>
	<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
	<link rel="stylesheet" href="twocolumn.css">
</head>

<body>
	<br/>
	<div id="header"><h1>Латино-американский танец Румба</h1></div>
	<div id="sidebar"><!--#echo encoding="none" var="rumba_menu" --></div>
	<div id="content"><!--#echo encoding="none" var="rumba_content" --></div>
</body>
</html>

twocolumn.css

body {
	margin: 0 auto;
	width: 640px;
	font:17px/20px Arial,Helvetica,sans-serif;
	overflow-y: scroll;
}
a {
	color: #777;
}
#header {
	padding: 10px;
	text-align: center;
}
#content {
	margin-left: 230px;
}
#content h2{
	color: #E6B03E;
}
#sidebar {
	padding: 10px;
	background: #B44E29;
	float: left;
	width: 180px;
}
#sidebar ul {
	padding: 0px;
}
#sidebar li {
	padding: 5px;
	list-style-type: none;
	list-style-position: inside;
}
#sidebar a {
	color: #fff;
	text-decoration: none;
}
#sidebar a:hover {
	color: #ccc;
	text-decoration: none;
}

SSI и БД в XML

Вещи нездешней формы, люстры, шкатулки, бра.
Медные пра-телефоны, чайники — тоже «пра»...

Минимализм языка SSI конечно не даст сильно развернуться. Но как же выкрутиться? Если немного прищуриться, глядя на html, он становится похож на xhtml, а если вообще закрыть глаза… Ну, вы уже поняли, что попробуем скрестить SSI с XML. Этот формат одним людям нравится, другие его люто ненавидят, но он «имеет место быть». Почему бы не попробовать?

Сделать из html-базы предыдущего примера xml файл — дело двух минут. Мы можем скормить его поисковой системе: Гуглу, Яндексу, Рамблеру, но не Мэйлу (предлагаю mail.ru начать индексировать xml файлы, кто за?). Поисковик воспримет файл как одну страничку и будет её учитывать именно так. С точки зрения предыдущего варианта с множеством страниц это скорее минус, но раз существует понятие Single-Page Application (SPA или Одностраничное приложение), значит эта xml страница может иметь право на жизнь*.

Однако xml файл как-то не очень похож на сайт, и показывать его в таком виде посетителю не резон. Вот тут и появляется необходимость подключения XSLT преобразования. Это обычный xsl файл, который также, как и предыдущий вариант движка, получает посредством QUERY_STRING с помощью SSI запрос и трансформирует xml файл. Результатом становится оформленная страничка, привычная посетителю. Хочу подчеркнуть, что XSLT-трансформация происходит на клиенте, т.е. её делает браузер, а не сервер.

Важно, что «одним движением руки» боковое меню со списком страниц генерируется автоматически. Кроме того, очень легко добавить в этот прототип движка разделы (категории) статей и теги (метки). Эта задача прямо-таки просится в xsl, и при желании можно нафантазировать много чего.

Поскольку сайт на XSLT версии SSI движка мы называем SPA, то с точки зрения SEO это важно. Это значит, что поисковая система видит одну страничку (ПС могут больше, так что я утрирую), и продвигать её необходимо как сайт-одностраничник. Это скорее минус, но с оговоркой. Xsl файл может при трансформации изменять контент. Это интересно. Допустим, с позиции SEO мы вынуждены добавить на сайт текст именно для ПС. Его можно задвинуть далеко в футер, а можно… просто не показывать посетителю. Насколько далеко в этом стоит заходить и стоит ли это делать вообще — это тема отдельного разговора, здесь же разговор только о технической возможности.

Теперь о трансформации на клиенте: аргумент переноса нагрузки с сервера на клиент я особо не рассматривал, кто-то это посчитает плюсом, кто-то скажет, что это экономия на спичках. Моё мнение — если возможно, лучше всё делать на сервере, но если нет, то тут выбор не велик. У браузеров к сожалению есть некоторые особенности в реализации XSLT (фичи или баги), которые надо знать и учитывать, разрабатывая xsl. Также, мне видится перспективным попробовать использовать не Апач, а Nginx, в этом случае есть вариант с использованием модуля ngx_http_xslt_module При этом сайт из SPA можно превратить в многостраничник, проводящий XSLT трансформацию на стороне сервера.

Эти файлы нужно создать на сайте, чтобы увидеть пример в действии:

.htaccess

AddDefaultCharset utf-8

AddType text/xml .xml
AddHandler server-parsed .xml
AddType text/xsl .xsl
AddHandler server-parsed .xsl
DirectoryIndex rumba.xml?query=start

RewriteEngine on
RewriteRule ^([a-zA-Z0-9-]+).html$ rumba.xml?query=$1 [L]

rumba.xml

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl"  href="rumba.xsl?<!--#echo encoding="none" var="QUERY_STRING" -->"?>
<html>
<head>
	<title>Латино-американский танец Румба</title>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
	<meta name="Description" content="Описание сайта"/>
</head>
<body>
	<h1>Латино-американский танец Румба</h1>
	<article id='start'>
		<h2>Румба — парный кубинский танец африканского происхождения</h2>
		<text>
			<a title='Оригинал статьи на Википедии' rel='canonical' href='https://ru.wikipedia.org/wiki/Румба'>Ру́мба</a> (исп. rumba) — у этого слова есть два различных значения:
			<ol>
			<li>Одно из них относится к направлению танцев и музыке, родившихся на Кубе. Наиболее известным из них является rumba Guaguanco. Так же популярными являются rumba Yambu и rumba Columbia. Каждый из этих видов румбы имеет свою стилистику музыки и танцевания, но в целом они очень близки.</li>
			<li>Другое значение появилось сравнительно недавно и относится к танцу из программы бальных танцев, который входит в программу соревнований. В этом значении румба является самым медленным из пяти танцев соревновательной латино-американской программы (остальные четыре — пасодобль, самба, ча-ча-ча и джайв). Танец и музыка румбы из соревновательной программы латино-американских танцев происходят от кубинских музыкальных стилей и танцев болеро и сон.</li>
			</ol>
		</text>
	</article>
	<article id='history'>
		<h2>История румбы</h2>
		<text>
			Румба появилась в Гаване в 19-м веке в комбинации с европейским контрдансом. Название «Rumba», возможно, происходит от названия танцевальных групп в 1807 году — «rumboso orquestra», хотя в Испании слово «rumbo» означает «путь» (в русском морской аналог — «румбы», то есть направление). Замечание - российская морская терминология аккуратно заимствована у Нидерландов, поэтому 'направление' очевидно не в русском, а в голландском не так.
		</text>
	</article>
	<article id='cha-cha-cha'>
		<h2>Румба и Ча-ча-ча</h2>
		<text>
			<p>Изначально не существовало четкого разделения танцев румба дансона и ча-ча-ча, из-за чего вся музыка, характерным образом обыгрывавшая первую долю (несколько ударов из затакта, приводящих к первой доле), подпадала под категорию румбы. Со временем танцы четко разделились. Музыка румбы дансона приобрела более медленный темп, стала сочиняться, как правило, в минорном ладу, и приобрела свое обыгрывание первой доли (ударные: восьмая, восьмая, восьмая, четверть — первая доля). Музыка ча-ча-ча стала быстрее, сочиняется как в мажорном, так и в минорном ладу и имеет собственное, очень выраженное и подчеркнутое обыгрывание первой доли (восьмая, восьмая, четверть — первая доля, так называемое — «ча-ча-ча» или «ча-ча-раз»).</p>
			<p>В связи с этим многие знаменитые в прошлом румбы с современной точки зрения следует считать скорее ча-ча-ча или даже вообще невозможно четко классифицировать как один из этих танцев. Так, например, знаменитая мелодия «Кукарача», считавшаяся румбой, не является ни ею, ни ча-ча-ча с современной точки зрения. «Guantanamera» более известна в варианте ча-ча-ча, а не румбы.</p>
			<p>Таким образом, румба обязана своим рождением религиозным ритуалам, развивалась она на базе ярко выраженных ритмов и хоровых голосов. Также можно сказать, что румбой в какой-то степени являются все те танцы, которые были созданы кубинцами. В настоящее время этот танец известен на всех континентах. Сначала он пришел в кабаре, а затем на телевидение. Существует бальная румба, но она существенно отличается от аутентичного кубинского варианта.</p>
		</text>
	</article>
	<article id='types'>
		<h2>Виды румбы</h2>
		<text>
			<p>В начале XIX века на Кубе существовало три варианта румбы, но широкую известность получила румба Гуагуанко (Guaguanco), танец, во время которого кавалер следует за дамой в поисках соприкосновения бедрами, а дама старается этого избежать. В этом танце дама как бы является объектом дерзкого ухаживания и старается сдержать страсть своего партнера. Возможно из-за этого за румбой и закрепилось название - «танец любви».</p>
			<p>Так-же на Кубе существовали различные виды румбы, которые танцевались на праздниках и просто сборищах людей на улице. Ярким представителем является Румба Миметика, в которой изображаются различные сцены из жизни простых людей (Papilote, Mama'buela, Gavilan)</p>
			<p>Коренную эволюцию румба претерпела, будучи вывезенной в США. Наравне с экспансивной, эротичной кубинской появилась Румба американская – с более сдержанными движениями и стилем. Именно этот вариант румбы и распространился по всему миру, завоевав сердца нескольких поколений танцоров и просто ценителей латиноамериканской культуры. Гуагуанко в основном состоит из ритмов африканских барабанов, которые накладываются на ритм клавэ (clave), представляющий смещенный акцент, известный как 3-2. Пение без музыкального сопровождение напоминает старинные испанские мелодии, которые накладываются на ритмы африканских барабанов. Исполняется гуагуанко одним или несколькими солистами, тему и слова придумывают по ходу исполнения песни. Структура ритма гуагуанко основывается чаще всего на ритме румбы сон (Rumba Son).</p>
		</text>
	</article>
	<article id='emotion'>
		<h2>Эмоциональное содержание танца</h2>
		<text>
			Среди всех бальных танцев румба характеризуется наиболее глубоким эмоциональным содержанием. В ходе своей эволюции румба приобрела многие черты, характерные для блюза. Существует расхожий штамп, что «румба — танец любви». Контраст ярко выраженного эротического характера танца и драматического содержания музыки создаёт неповторимый эстетический эффект. Вопреки всеобщему мнению о том, что движения в румбе — это танцевальное воплощение эротических чувств, румба изначально была свадебным танцем, а ее движения обозначали не что иное как семейные обязанности супругов. Немногочисленные современные румбы, написанные в мажоре, имеют свою изюминку, но не оставляют такого глубокого впечатления.
		</text>
	</article>
	<article id='hits'>
		<h2>Хиты написанные в ритме румбы</h2>
		<text>
			<ul>
			<li>La Media Vuelta — Эйди Горме (Eydie Gorme)</li>
			<li>Manana</li>
			<li>Cantinero de Cuba</li>
			<li>Reflection — Кристина Агилера</li>
			<li>Fairy tale — Тони Брэкстон</li>
			<li>Don't Know Why — Нора Джонс</li>
			<li>Falling Into You — Celine Dion</li>
			<li>When the blue bird sings</li>
			<li>Gipsy Kings — La Rumba-De Nicolas</li>
			<li>Gipsy Kings — Una Rumba Por Aqui</li>
			<li>Gipsy Kings — Rumba Del Stud</li>
			</ul>
		</text>
	</article>
</body>
</html>

rumba.xsl

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<!--#if expr="$QUERY_STRING = /^query=([a-zA-Z0-9-]+)/" -->
	<!--#set var="rumba_query" value="$1" -->
<!--#else -->
	<!--#set var="rumba_query" value="error" -->
<!--#endif -->
	
<xsl:param name="query"><!--#echo encoding="none" var="rumba_query" --></xsl:param>

<xsl:template match="/">
	<html>
	<head>
		<xsl:apply-templates select="/html/head"/>
		<link rel="stylesheet" href="twocolumn.css"/>
	</head>
	<body>
		<div id="header">
			<xsl:apply-templates select="/html/body" mode="header"/>
		</div>
		<div id="sidebar">
			<ul>
				<xsl:apply-templates select="/html/body/article"/>
			</ul>
		</div>
		<div id="content">
			<xsl:choose> 
				<xsl:when test="count(/html/body/article[@id = $query]) = '0'"> 
					<xsl:apply-templates select="/html/body" mode="error"/>
				</xsl:when> 
				<xsl:otherwise> 
					<xsl:apply-templates select="/html/body" mode="page"/>
				</xsl:otherwise> 
			</xsl:choose> 
		</div>
	</body>
	</html>
</xsl:template>

<xsl:template match="/html/head">
	<title><xsl:value-of select="/html/body/article[@id = $query]/h2"/></title>
	<xsl:copy-of select="meta"/>
</xsl:template>

<xsl:template match="body" mode="header">
		<xsl:copy-of select="h1"/>
</xsl:template>

<xsl:template match="/html/body/article">
     <xsl:choose> 
          <xsl:when test="@id = 'start'"> 
               <li><a href="./">Главная</a></li>
          </xsl:when> 
          <xsl:otherwise> 
               <li><a href="{@id}.html" rel="nofollow"><xsl:value-of select="h2"/></a></li>
          </xsl:otherwise> 
     </xsl:choose> 
</xsl:template>

<xsl:template match="/html/body" mode="page">
	<xsl:for-each select="/html/body/article[@id = $query]">
		<xsl:copy-of select="h2"/>
		<div>
		   <xsl:copy-of select="text"/> 
		</div>
	 </xsl:for-each> 
</xsl:template>

<xsl:template match="/html/body" mode="error">
	<h2>Ошибка 404</h2>
	Страница не найдена
</xsl:template>

</xsl:stylesheet>

twocolumn.css

body {
	margin: 0 auto;
	width: 640px;
	font:17px/20px Arial,Helvetica,sans-serif;
	overflow-y: scroll;
}
a {
	color: #777;
}
#header {
	padding: 10px;
	text-align: center;
}
#content {
	margin-left: 230px;
}
#content h2{
	color: #E6B03E;
}
#sidebar {
	padding: 10px;
	background: #B44E29;
	float: left;
	width: 180px;
}
#sidebar ul {
	padding: 0px;
}
#sidebar li {
	padding: 5px;
	list-style-type: none;
	list-style-position: inside;
}
#sidebar a {
	color: #fff;
	text-decoration: none;
}
#sidebar a:hover {
	color: #ccc;
	text-decoration: none;
}

Субъективный вывод

Кто-нибудь — между прочим — скажет о наших годах:
«Всё тогда было проще… Господи, нам бы так!..»

Применения описанных решений на SSI однозначно не подходят для широкого применения. Но сугубо с технической точки зрения они могут быть применены, и по сути это очень простые и весьма надёжные решения, о которых не лишним будет помнить. Альтернативой им служат современные CMS и SPA, использующие JavaScript, PHP и пр. которые скорей всего и будут решать поставленные по созданию сайта задачи.

Кстати говоря, вполне можно реализовать xslt трансформацию и в РНР и в JavaScript (не сомневаюсь, что и в других языках тоже), но я рассматривал решение с SSI с минимальным стеком технологий, этакий аскетический и минималистический вариант, когда есть сервер, или даже шаред хостинг и… всё. Я не рассмотрел версию с JS, хранящим данные без всякого Ajax: этот вариант не только может существовать, но и когда-то был использован мной в начале двухтысячных, но это по сути очень близко к современному SPA с каким-нибудь AngularJS на борту, и думаю, статей на эту тему и так хватает.

Если нет желания собирать сайты из приведённых примеров, вот ссылки на SSI HTML и SSI XML.

* Термины SPA и одностраничник мной в некоторой степени приравнены, хотя это конечно разные вещи.

Автор: claygod

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js