📜 ⬆️ ⬇️

SSI website: HTML, XML, XSLT

image
Honorable Retro! Good or evil?
What wind sigh brought you to us?
© Robert Christmas

There are things that just like them, they are pleasant to hold in their hands, they are simple, they are understandable. Their heyday is gone, but they themselves have not sunk into oblivion, and they come back again and again. This applies not only to the material world. There is always a programmer who is interested in writing in assembler, or directly in machine codes, a lover of simplicity, minimalism, retro. Let's try to go back to SSI, good, it's simpler than assembler, and much younger.

The SSI technology at one time allowed (and now allows) the creation of sites in which part of the content was put into a separate file that is turned on by the server on the fly. Usually in separate files were carried out: the leader, the sidebar, the footer. For a regular site with a simple structure, this is more than enough. The win was in the fact that they used simple, fast and reliable solutions that actually implemented the CMS functionality without programming. Anyway, the minimum technology stack is curious.

A typical page of the site "on the roads" looked like this:

<html> <head> <title> </title> </head> <body> <div id="header"><!--#include virtual="/header.html" --></div> <div id="sidebar"><!--#include virtual="/sidebar.html" --></div> <div id="footer"><!--#include virtual="/footer.html" --></div> </body> </html> 

But working with multiple pages caused some inconvenience. There were CMS, which removed some questions, and put others. An interesting solution was to store the database in the form of a single html file, in which the pages were denoted by the tags H1, H2, and H3. In this case, the tag number said in the nesting page. I observed this idea in CMSimple cmsimple.org , although it is possible that someone came up with it earlier. On the basis of this idea, a lot of CMS were probably created (and I tried it myself, I confess, what could be there).
')
The main drawback of this solution is the need to roll a large html file. There is certainly an opportunity to make an index, but by and large it is not so interesting. It's one thing to edit a dozen articles in one file, another one thousands. We take it for granted that such an engine is appropriate for a small site, and it does not matter, it is a satellite or a satellite - we are discussing technology.

SSI and DB in HTML


What kind of fashion bends? The time has gone mad:
Grandmothers dressers in block climb home!

Having recollected SSI, I asked myself a question: is it possible to implement such an approach using this technology? No sooner said than done. Directly in the html file you can create a variable, the value of which will be the site database:

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

It remains to learn how to make a selection of this database. For this useful variable QUERY_STRING, which stores the query string to the site. Having set up rewright in htaccess and using the possibility of conditional expressions with support of regular expressions (sorry for tautology), the server will be able to select the necessary article from the database.

Unfortunately, there are no cycles in SSI , therefore, going through the database and forming the sidebar with the list of pages will not work: you will have to do it manually. Awkward, but these are SSI limitations. Also, I didn’t have enough opportunity to place in the variable content of the site, something like this:

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

Such an option would allow the database to be placed in a separate file, so the “engine” code would be cleaner and more readable. So "noodle code" is our everything.

For the experiment, I decided to make a simple site to try in the proposed solution. The theme is the Latin-American dance Rumba (source code below). First impression - the site is fast. Since the size of the “engine” along with the database is a little over 10 kilobytes, this is not surprising. We write this in plus. Plus, this will remain so until the size of the database does not grow, for example, to a megabyte. At the same time, the need to create the menu manually will stop from sculpting a large site much earlier. In addition, copy-paste something in the database, you must not forget to replace the double quotation marks with single quotes.

Nothing unusual and complicated. It is a possible solution. It is important that the pages due to rewrite search engines will be indexed as separate, and not as one. This of course will not surprise anyone, but mentioning does not hurt. Also, plus write down a small load on the server. Not the most important factor for a small site, but let it be. If there is a desire to fasten descriptors - this is also not a problem, it is enough to enter another tag into the markup of the article entries.

These files need to be created on the site to see an example in action:

.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 and DB in XML


Things of another form, chandeliers, boxes, sconces.
Copper pra-phones, kettles - also "great" ...

The minimalism of the SSI language of course will not give much to turn. But how to get out? If you squint a little, looking at html, it becomes similar to xhtml, and if you close your eyes at all ... Well, you already understand that we are trying to cross-SSI with XML. Some people like this format, others hate it fiercely, but it "has a place to be." Why not try?

To make an html-base of the previous example xml file is a matter of two minutes. We can feed it to the search engine: Google, Yandex, Rambler, but not Mail (I suggest mail.ru to start indexing xml files, who is for?). The search engine will take the file as one page and will take it into account that way. From the point of view of the previous version with multiple pages, this is rather a minus, but since there is the concept of Single-Page Application ( SPA or Single-Page Application), then this xml page may have the right to life *.

However, the xml file is somehow not very similar to the site, and it’s not reasonable to show it in this form to the visitor. This is where the need to connect XSLT transform appears. This is a regular xsl file, which also, like the previous version of the engine, receives a request via QUERY_STRING using SSI and transforms the xml file. The result is a decorated page, familiar to the visitor. I want to emphasize that the XSLT transformation takes place on the client, i.e. it makes the browser, not the server.

It is important that by “one hand movement” the side menu with the list of pages is generated automatically. In addition, it is very easy to add sections (categories) of articles and tags (tags) to this prototype of the engine. This task is really asking for xsl, and if you like, you can dream up a lot of things.

Since the site on the XSLT version of the SSI engine we call SPA, from the point of view of SEO, this is important. This means that the search engine sees one page (PS can be more, so I exaggerate), and it is necessary to promote it as a one-page site. It is rather a minus, but with a reservation. Xsl file can change content during transformation. It is interesting. Suppose, from the SEO point of view, we are forced to add text to the site specifically for PS. It can be pushed far into the footer, and you can ... just not show it to the visitor. How far it is worth going into it and whether it is worth doing it at all is a topic for a separate conversation, but here we are talking only about the technical possibility.

Now about the transformation on the client: I did not particularly consider the argument of transferring the load from the server to the client, someone will consider it a plus, someone will say that this is a savings on matches. My opinion - if possible, it is better to do everything on the server, but if not, then the choice is not great. Browsers unfortunately have some features in the XSLT implementation (features or bugs) that need to be known and taken into account when developing xsl. Also, I see it as promising to try to use not Apache, but Nginx, in this case there is an option using the ngx_http_xslt_module module. At the same time, the site from the SPA can be turned into a multipage page that performs the XSLT transformation on the server side.

These files need to be created on the site to see an example in action:

.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; } 


Subjective conclusion


Someone - by the way - will say about our years:
“Everything was then easier ... God, we would be like that! ..”

Applications of the solutions described on SSI are definitely not suitable for widespread use. But purely from a technical point of view, they can be applied, and in fact these are very simple and very reliable solutions, which will not be superfluous to remember. An alternative to them are modern CMS and SPA, which use JavaScript, PHP, etc., which most likely will solve the tasks posed to create the site.

, xslt JavaScript ( , ), SSI , , , … . JS, Ajax: , - , SPA - AngularJS , , .

, SSI HTML SSI XML .

* SPA , .

Source: https://habr.com/ru/post/276491/


All Articles