mirror of
https://github.com/standardebooks/web.git
synced 2025-07-14 02:21:55 -04:00
Add XSLT stylesheet for OPDS feeds
This commit is contained in:
parent
3b26e49509
commit
305a9d298b
10 changed files with 182 additions and 56 deletions
|
@ -86,6 +86,10 @@ class OpdsFeed{
|
|||
|
||||
file_put_contents($parentFilepath, str_replace(" ns=", " xmlns=", $xmlString));
|
||||
|
||||
// If we include this stylsheet declaration in the OPDS template, `se clean` will remove it and also
|
||||
// add a bunch of empty namespaces in the output. So, add it programatically here instead.
|
||||
file_put_contents($tempFilename, str_replace("?>", "?>\n<?xml-stylesheet href=\"/opds/style\" type=\"text/xsl\"?>", file_get_contents($tempFilename)));
|
||||
|
||||
rename($tempFilename, $path);
|
||||
}
|
||||
else{
|
||||
|
|
|
@ -8,7 +8,7 @@ $collection = $collection ?? null;
|
|||
|
||||
$ebooks = $ebooks ?? [];
|
||||
?>
|
||||
<ol<? if($view == VIEW_LIST){ ?> class="list"<? } ?><? if($collection !== null){ ?> typeof="schema:BookSeries" about="<?= $collection->Url ?>"<? } ?>>
|
||||
<ol class="ebooks-list<? if($view == VIEW_LIST){ ?> list<? }else{ ?> grid<? } ?>"<? if($collection !== null){ ?> typeof="schema:BookSeries" about="<?= $collection->Url ?>"<? } ?>>
|
||||
<? if($collection !== null){ ?>
|
||||
<meta property="schema:name" content="<?= Formatter::ToPlainText($collection->Name) ?>"/>
|
||||
<? } ?>
|
||||
|
|
|
@ -4,8 +4,9 @@
|
|||
<? foreach($ebook->Authors as $author){ ?>
|
||||
<author>
|
||||
<name><?= htmlspecialchars($author->Name, ENT_QUOTES|ENT_XML1, 'utf-8') ?></name>
|
||||
<? if($author->WikipediaUrl !== null){ ?><uri><?= htmlspecialchars($author->WikipediaUrl, ENT_QUOTES|ENT_XML1, 'utf-8') ?></uri><? } ?>
|
||||
<uri><?= SITE_URL . htmlspecialchars($ebook->AuthorsUrl, ENT_QUOTES|ENT_XML1, 'utf-8') ?></uri>
|
||||
<? if($author->FullName !== null){ ?><schema:alternateName><?= htmlspecialchars($author->FullName, ENT_QUOTES|ENT_XML1, 'utf-8') ?></schema:alternateName><? } ?>
|
||||
<? if($author->WikipediaUrl !== null){ ?><schema:sameAs><?= htmlspecialchars($author->WikipediaUrl, ENT_QUOTES|ENT_XML1, 'utf-8') ?></schema:sameAs><? } ?>
|
||||
<? if($author->NacoafUrl !== null){ ?><schema:sameAs><?= htmlspecialchars($author->NacoafUrl, ENT_QUOTES|ENT_XML1, 'utf-8') ?></schema:sameAs><? } ?>
|
||||
</author>
|
||||
<? } ?>
|
||||
|
|
|
@ -10,15 +10,18 @@
|
|||
|
||||
$isCrawlable = $isCrawlable ?? false;
|
||||
|
||||
// Note that the XSL stylesheet gets stripped during `se clean` when we generate the OPDS feed.
|
||||
// `se clean` will also start adding empty namespaces everywhere if we include the stylesheet declaration first.
|
||||
// We have to add it programmatically when saving the OPDS file.
|
||||
print("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
|
||||
?>
|
||||
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:schema="http://schema.org/"<? if($isCrawlable){ ?> xmlns:fh="http://purl.org/syndication/history/1.0"<? } ?>>
|
||||
<id><?= $id ?></id>
|
||||
<link href="<?= $url ?>" rel="self" type="application/atom+xml;profile=opds-catalog;kind=acquisition"/>
|
||||
<link href="/opds" rel="start" type="application/atom+xml;profile=opds-catalog;kind=navigation"/>
|
||||
<link href="<?= $parentUrl ?>" rel="up" type="application/atom+xml;profile=opds-catalog;kind=navigation"/>
|
||||
<link href="/opds/all" rel="http://opds-spec.org/crawlable" type="application/atom+xml;profile=opds-catalog;kind=acquisition"/>
|
||||
<link href="/ebooks/opensearch" rel="search" type="application/opensearchdescription+xml"/>
|
||||
<link href="<?= SITE_URL . $url ?>" rel="self" type="application/atom+xml;profile=opds-catalog;kind=acquisition"/>
|
||||
<link href="<?= SITE_URL ?>/opds" rel="start" type="application/atom+xml;profile=opds-catalog;kind=navigation"/>
|
||||
<link href="<?= SITE_URL ?><?= $parentUrl ?>" rel="up" type="application/atom+xml;profile=opds-catalog;kind=navigation"/>
|
||||
<link href="<?= SITE_URL ?>/opds/all" rel="http://opds-spec.org/crawlable" type="application/atom+xml;profile=opds-catalog;kind=acquisition"/>
|
||||
<link href="<?= SITE_URL ?>/ebooks/opensearch" rel="search" type="application/opensearchdescription+xml"/>
|
||||
<title><?= htmlspecialchars($title, ENT_QUOTES|ENT_XML1, 'utf-8') ?></title>
|
||||
<subtitle>Free and liberated ebooks, carefully produced for the true book lover.</subtitle>
|
||||
<icon>/images/logo.png</icon>
|
||||
|
|
|
@ -7,15 +7,19 @@
|
|||
- The <fh:complete/> element is required to note this as a "Complete Acquisition Feeds"; see https://specs.opds.io/opds-1.2#25-complete-acquisition-feeds
|
||||
|
||||
*/
|
||||
|
||||
// Note that the XSL stylesheet gets stripped during `se clean` when we generate the OPDS feed.
|
||||
// `se clean` will also start adding empty namespaces everywhere if we include the stylesheet declaration first.
|
||||
// We have to add it programmatically when saving the OPDS file.
|
||||
print("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
|
||||
?>
|
||||
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:schema="http://schema.org/">
|
||||
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
<id><?= $id ?></id>
|
||||
<link href="<?= $url ?>" rel="self" type="application/atom+xml;profile=opds-catalog;kind=acquisition"/>
|
||||
<link href="/opds" rel="start" type="application/atom+xml;profile=opds-catalog;kind=navigation"/>
|
||||
<link href="/opds/all" rel="http://opds-spec.org/crawlable" type="application/atom+xml;profile=opds-catalog;kind=acquisition"/>
|
||||
<link href="/ebooks/opensearch" rel="search" type="application/opensearchdescription+xml"/>
|
||||
<? if($parentUrl !== null){ ?><link href="<?= $parentUrl ?>" rel="up" type="application/atom+xml;profile=opds-catalog;kind=navigation"/><? } ?>
|
||||
<link href="<?= SITE_URL . $url ?>" rel="self" type="application/atom+xml;profile=opds-catalog;kind=acquisition"/>
|
||||
<link href="<?= SITE_URL ?>/opds" rel="start" type="application/atom+xml;profile=opds-catalog;kind=navigation"/>
|
||||
<link href="<?= SITE_URL ?>/opds/all" rel="http://opds-spec.org/crawlable" type="application/atom+xml;profile=opds-catalog;kind=acquisition"/>
|
||||
<link href="<?= SITE_URL ?>/ebooks/opensearch" rel="search" type="application/opensearchdescription+xml"/>
|
||||
<? if($parentUrl !== null){ ?><link href="<?= SITE_URL ?><?= $parentUrl ?>" rel="up" type="application/atom+xml;profile=opds-catalog;kind=navigation"/><? } ?>
|
||||
<title><?= htmlspecialchars($title, ENT_QUOTES|ENT_XML1, 'utf-8') ?></title>
|
||||
<subtitle>Free and liberated ebooks, carefully produced for the true book lover.</subtitle>
|
||||
<icon>/images/logo.png</icon>
|
||||
|
|
|
@ -1186,7 +1186,22 @@ main.ebooks > aside.alert + ol{
|
|||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
main.ebooks > ol{
|
||||
.opds ol.ebooks-list.list{
|
||||
margin-top: 4rem;
|
||||
}
|
||||
|
||||
.opds .download{
|
||||
font-weight: bold;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
|
||||
.opds .download + ul,
|
||||
.opds .download + ul > li{
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
ol.ebooks-list.grid{
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
grid-gap: 4rem;
|
||||
|
@ -1195,7 +1210,7 @@ main.ebooks > ol{
|
|||
list-style: none;
|
||||
}
|
||||
|
||||
main.ebooks > ol.list{
|
||||
ol.ebooks-list.list{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0;
|
||||
|
@ -1205,50 +1220,54 @@ main.ebooks > ol.list{
|
|||
max-width: 30rem;
|
||||
}
|
||||
|
||||
main.ebooks > ol > li{
|
||||
ol.ebooks-list > li{
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
main.ebooks > ol.list > li{
|
||||
ol.ebooks-list.list > li{
|
||||
display: grid;
|
||||
grid-template-columns: 6rem 1fr;
|
||||
grid-column-gap: 1rem;
|
||||
grid-template-rows: auto auto 1fr;
|
||||
}
|
||||
|
||||
main.ebooks > ol.list > li + li {
|
||||
ol.ebooks-list.list > li + li {
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
main.ebooks > ol.list > li > a{
|
||||
ol.ebooks-list.list > li > a{
|
||||
grid-row: 1 / span 3;
|
||||
}
|
||||
|
||||
main.ebooks > ol.list ul.tags{
|
||||
.opds ol.ebooks-list.list > li > a{
|
||||
grid-row: 1 / span 5;
|
||||
}
|
||||
|
||||
ol.ebooks-list.list ul.tags{
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
margin-left: -.25rem;
|
||||
margin-top: .25rem;
|
||||
}
|
||||
|
||||
main.ebooks > ol.list ul.tags li{
|
||||
ol.ebooks-list.list ul.tags li{
|
||||
margin-left: .25rem;
|
||||
margin-top: .25rem;
|
||||
}
|
||||
|
||||
main.ebooks > ol.list > li p{
|
||||
ol.ebooks-list.list > li p{
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
main.ebooks > ol a[tabindex]{
|
||||
ol.ebooks-list a[tabindex]{
|
||||
display: inline-block;
|
||||
transition: all .2s ease;
|
||||
position: relative;
|
||||
font-size: 0;
|
||||
}
|
||||
|
||||
main.ebooks > ol a[tabindex][data-ordinal]::before{
|
||||
ol.ebooks-list a[tabindex][data-ordinal]::before{
|
||||
display: block;
|
||||
content: "№ "attr(data-ordinal);
|
||||
position: absolute;
|
||||
|
@ -1265,29 +1284,29 @@ main.ebooks > ol a[tabindex][data-ordinal]::before{
|
|||
color: var(--dark-body-text);
|
||||
}
|
||||
|
||||
main.ebooks > ol a[tabindex]:hover{
|
||||
ol.ebooks-list a[tabindex]:hover{
|
||||
transform: scale(1.05);
|
||||
color: unset;
|
||||
}
|
||||
|
||||
main.ebooks > ol a[tabindex]:hover img{
|
||||
ol.ebooks-list a[tabindex]:hover img{
|
||||
box-shadow: 3px 3px 1px rgba(0, 0, 0, .25);
|
||||
}
|
||||
|
||||
main.ebooks > ol > li a[tabindex]:active{
|
||||
ol.ebooks-list > li a[tabindex]:active{
|
||||
transform: scale(1.025);
|
||||
transition: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
main.ebooks > ol > li p{
|
||||
ol.ebooks-list > li p{
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
-webkit-hyphens: none;
|
||||
hyphens: none;
|
||||
}
|
||||
|
||||
main.ebooks > ol > li img{
|
||||
ol.ebooks-list > li img{
|
||||
box-sizing: border-box;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
|
@ -1295,24 +1314,27 @@ main.ebooks > ol > li img{
|
|||
border-radius: .25rem;
|
||||
}
|
||||
|
||||
main.ebooks > ol > li > p:nth-of-type(1) > a{
|
||||
ol.ebooks-list > li > p:nth-of-type(1) > a{
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
main.ebooks > ol.list > li p.author a,
|
||||
main.ebooks > ol.list > li > p:nth-of-type(1) > a{
|
||||
ol.ebooks-list.list > li p.author a,
|
||||
ol.ebooks-list.list > li > p:nth-of-type(1) > a{
|
||||
display: inline;
|
||||
}
|
||||
|
||||
main.ebooks > ol > li > a:first-child{
|
||||
ol.ebooks-list > li > a:first-child{
|
||||
font-size: 0; /* for correct focus outline */
|
||||
}
|
||||
|
||||
main.ebooks > ol > li p.author a{
|
||||
ol.ebooks-list > li p.author{
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
ol.ebooks-list > li p.author a{
|
||||
text-decoration: none;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
@ -1376,11 +1398,6 @@ figure{
|
|||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.rss ul.tags + p{
|
||||
font-style: italic;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
ul.tags{
|
||||
list-style: none;
|
||||
display: flex;
|
||||
|
@ -1485,7 +1502,7 @@ p.no-results{
|
|||
text-align: center;
|
||||
}
|
||||
|
||||
.us-pd-warning{
|
||||
.s-pd-warning{
|
||||
font-style: italic;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
@ -2479,8 +2496,13 @@ ul.feed p{
|
|||
margin: 0;
|
||||
}
|
||||
|
||||
ul.feed p:last-child{
|
||||
font-style: italic;
|
||||
.url{
|
||||
font-family: "Fira Mono", monospace;
|
||||
font-size: .8rem;
|
||||
}
|
||||
|
||||
.rss > li p:last-child{
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
@media (hover: none) and (pointer: coarse){ /* target ipads and smartphones without a mouse */
|
||||
|
@ -2655,7 +2677,7 @@ ul.feed p:last-child{
|
|||
}
|
||||
|
||||
@media(max-width: 900px){
|
||||
main.ebooks > ol{
|
||||
ol.ebooks-list.grid{
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
|
@ -2751,7 +2773,7 @@ ul.feed p:last-child{
|
|||
}
|
||||
|
||||
@media(max-width: 700px){
|
||||
main.ebooks > ol{
|
||||
ol.ebooks-list.grid{
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
|
@ -2995,7 +3017,7 @@ ul.feed p:last-child{
|
|||
}
|
||||
|
||||
@media(max-width: 470px){
|
||||
main.ebooks > ol{
|
||||
ol.ebooks-list.grid{
|
||||
grid-gap: 2rem;
|
||||
}
|
||||
|
||||
|
@ -3047,7 +3069,7 @@ ul.feed p:last-child{
|
|||
hyphens: auto;
|
||||
}
|
||||
|
||||
main.ebooks > ol{
|
||||
ol.ebooks-list.grid{
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
|
@ -3101,11 +3123,11 @@ ul.feed p:last-child{
|
|||
padding: 1rem;
|
||||
}
|
||||
|
||||
main.ebooks > ol.list > li{
|
||||
ol.ebooks-list.list > li{
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
main.ebooks > ol.list > li img{
|
||||
ol.ebooks-list.list > li img{
|
||||
max-width: 50%;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
@ -3141,8 +3163,8 @@ ul.feed p:last-child{
|
|||
article.ebook section#sources ul li a[class]::before,
|
||||
article.ebook #more-ebooks img,
|
||||
article.ebook #more-ebooks a:active img,
|
||||
main.ebooks > ol a[tabindex],
|
||||
main.ebooks > ol > li a[tabindex]:active,
|
||||
ol.ebooks-list a[tabindex],
|
||||
ol.ebooks-list > li a[tabindex]:active,
|
||||
label.select > span + span::after,
|
||||
label.search:focus-within::before,
|
||||
label.search:hover::before,
|
||||
|
|
|
@ -64,7 +64,7 @@ input::placeholder{
|
|||
color: rgba(255, 255, 255, .75);
|
||||
}
|
||||
|
||||
main.ebooks > ol img:hover{
|
||||
ol.ebooks-list img:hover{
|
||||
box-shadow: 3px 3px 1px rgba(0, 0, 0, .5);
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ require_once('Core.php');
|
|||
<ul class="feed">
|
||||
<li>
|
||||
<p><a href="/rss/new-releases">New releases</a> (RSS 2.0)</p>
|
||||
<p><?= SITE_URL ?>/rss/new-releases</p>
|
||||
<p class="url"><?= SITE_URL ?>/rss/new-releases</p>
|
||||
<p>A list of the thirty latest Standard Ebooks ebook releases, most-recently-released first.</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
@ -29,9 +29,8 @@ require_once('Core.php');
|
|||
<p><a href="https://en.wikipedia.org/wiki/Open_Publication_Distribution_System">OPDS feeds</a> are designed for use with ereading systems like <a href="http://koreader.rocks/">KOreader</a> or <a href="https://calibre-ebook.com">Calibre</a>, or with ereaders like <a href="https://johnfactotum.github.io/foliate/">Foliate</a>. They allow you to search, browse, and download from our catalog, directly in your ereader.</p>
|
||||
<ul class="feed">
|
||||
<li>
|
||||
<p><a href="/opds">The Standard Ebooks OPDS feed</a> (OPDS 1.1)</p>
|
||||
<p><?= SITE_URL ?>/opds</p>
|
||||
<p>The main OPDS feed to use with ereading systems that support OPDS.</p>
|
||||
<p><a href="/opds">The Standard Ebooks OPDS feed</a> (OPDS 1.2)</p>
|
||||
<p class="url"><?= SITE_URL ?>/opds</p>
|
||||
</li>
|
||||
</ul>
|
||||
<section>
|
||||
|
|
93
www/opds/style.php
Normal file
93
www/opds/style.php
Normal file
|
@ -0,0 +1,93 @@
|
|||
<?
|
||||
require_once('Core.php');
|
||||
|
||||
// `text/xsl` is the only mime type recognized by Chrome for XSL stylesheets
|
||||
header('Content-Type: text/xsl');
|
||||
print("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n")
|
||||
?>
|
||||
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:atom="http://www.w3.org/2005/Atom">
|
||||
<xsl:output method="html" html-version="5.0" encoding="utf-8" indent="yes" doctype-system="about:legacy-compat"/> <? /* doctype-system outputs the HTML5 doctype */ ?>
|
||||
<xsl:template match="/">
|
||||
<?= Template::Header(['xmlDeclaration' => false]) ?>
|
||||
<main class="opds">
|
||||
<h1><xsl:value-of select="/atom:feed/atom:title"/></h1>
|
||||
<p>This page is an OPDS feed. The URL in your browser’s address bar (<a class="url"><xsl:attribute name="href"><xsl:value-of select="/atom:feed/atom:link[@rel='self']/@href"/></xsl:attribute><xsl:value-of select="/atom:feed/atom:link[@rel='self']/@href"/></a>) can be used in any OPDS client.</p>
|
||||
<xsl:if test="/atom:feed/atom:entry[./atom:link[starts-with(@type, 'application/atom+xml;profile=opds-catalog;kind=')]]">
|
||||
<ol class="rss">
|
||||
<xsl:for-each select="/atom:feed/atom:entry[./atom:link[starts-with(@type, 'application/atom+xml;profile=opds-catalog;kind=')]]">
|
||||
<li>
|
||||
<a>
|
||||
<xsl:attribute name="href">
|
||||
<xsl:value-of select="atom:link/@href"/>
|
||||
</xsl:attribute>
|
||||
<xsl:value-of select="atom:title"/>
|
||||
</a>
|
||||
<p>
|
||||
<xsl:value-of select="atom:content"/>
|
||||
</p>
|
||||
</li>
|
||||
</xsl:for-each>
|
||||
</ol>
|
||||
</xsl:if>
|
||||
<xsl:if test="/atom:feed/atom:entry[./atom:link[@rel='http://opds-spec.org/acquisition/open-access']]">
|
||||
<ol class="ebooks-list list">
|
||||
<xsl:for-each select="/atom:feed/atom:entry[./atom:link[@rel='http://opds-spec.org/acquisition/open-access']]">
|
||||
<li>
|
||||
<a tabindex="-1">
|
||||
<xsl:attribute name="href">
|
||||
<xsl:value-of select="atom:link[@rel='related']/@href"/>
|
||||
</xsl:attribute>
|
||||
<img alt="The cover for the Standard Ebooks edition of Winnie-the-Pooh, by A. A. Milne" width="224" height="335">
|
||||
<xsl:attribute name="src">
|
||||
<xsl:value-of select="atom:link[@rel='http://opds-spec.org/image/thumbnail']/@href"/>
|
||||
</xsl:attribute>
|
||||
</img>
|
||||
</a>
|
||||
<p>
|
||||
<a>
|
||||
<xsl:attribute name="href">
|
||||
<xsl:value-of select="atom:link[@rel='related']/@href"/>
|
||||
</xsl:attribute>
|
||||
<xsl:value-of select="atom:title"/>
|
||||
</a>
|
||||
</p>
|
||||
<div>
|
||||
<xsl:for-each select="atom:author">
|
||||
<p class="author">
|
||||
<a>
|
||||
<xsl:attribute name="href">
|
||||
<xsl:value-of select="atom:uri"/>
|
||||
</xsl:attribute>
|
||||
<xsl:value-of select="atom:name"/>
|
||||
</a>
|
||||
</p>
|
||||
</xsl:for-each>
|
||||
</div>
|
||||
<div class="details">
|
||||
<p>
|
||||
<xsl:value-of select="atom:summary"/>
|
||||
</p>
|
||||
</div>
|
||||
<p class="download">Download</p>
|
||||
<ul>
|
||||
<xsl:for-each select="atom:link[@rel='http://opds-spec.org/acquisition/open-access']">
|
||||
<li>
|
||||
<p>
|
||||
<a>
|
||||
<xsl:attribute name="href">
|
||||
<xsl:value-of select="@href"/>
|
||||
</xsl:attribute>
|
||||
<xsl:value-of select="@title"/>
|
||||
</a>
|
||||
</p>
|
||||
</li>
|
||||
</xsl:for-each>
|
||||
</ul>
|
||||
</li>
|
||||
</xsl:for-each>
|
||||
</ol>
|
||||
</xsl:if>
|
||||
</main>
|
||||
<?= Template::Footer() ?>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
|
@ -12,7 +12,7 @@ print("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n")
|
|||
<main>
|
||||
<h1><xsl:value-of select="substring-after(/rss/channel/title, 'Standard Ebooks - ')"/></h1>
|
||||
<p><xsl:value-of select="/rss/channel/description"/></p>
|
||||
<p>This page is an RSS feed. The URL in your address bar (<a ><xsl:attribute name="href"><xsl:value-of select="/rss/channel/atom:link/@href"/></xsl:attribute><xsl:value-of select="/rss/channel/atom:link/@href"/></a>) can be used in any RSS reader.</p>
|
||||
<p>This page is an RSS feed. The URL in your browser’s address bar (<a class="url"><xsl:attribute name="href"><xsl:value-of select="/rss/channel/atom:link/@href"/></xsl:attribute><xsl:value-of select="/rss/channel/atom:link/@href"/></a>) can be used in any RSS reader.</p>
|
||||
<ol class="rss">
|
||||
<xsl:for-each select="/rss/channel/item">
|
||||
<li>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue