Pull to refresh

Преобразование FB2 в XHTML с сохранением вложенных рисунков

XSLT
Возникла у меня небольшая необходимость преобразовать книги в формате FB в xhtml.
Ну ясное дело я полез на www.gribuser.ru/xml/fictionbook/2.0/xsl/export где и взял файл
FB2_2_xhtml.xsl (заодно захватил FB2_2_txt.xsl мало ли в текстовом виде понадобится книжку получить )
Попробовал сконвертировать книжку, и заметил маленькую проблемку, рисунки то пропали. :(
В принципе рисунки не главное в книжке, но все равно немного обидно. Поэтому полезем разбираться в чем проблема.

По стандарту FB2 внедренные рисунки описываются в тегах binary.А ссылаются на них с указанием якоря в ссылке, то есть
<img src='#cover.jpg'/>



Сначала возникла мысль просто вытащить рисунки, и положить их в папку с преобразоваемым файлом. Получилось нечто вроде
<?php
$path='book'; //путь к папке куда будем складывать рисунки
$doc=new DOMDocument();
$doc->load($xml_filename);
$nodes=$doc->getElementsByTagName('binary');
foreach ($nodes as $node)
{
$value=base64_decode($node->nodeValue);
$fname= $node->attributes->getNamedItem('id')->nodeValue;
$fh=fopen($path.'/'.$fname,'w+');
fwrite($fh,$value);
fclose($fh);
}


Затем делаем xslt преобразование файлов взятым с офф сайта и радуемся жизнь, рисунки появились. Вот только объем, если делатаь небольшую библиотечку то надо хранить txt файлы, fb2 файлы, xhtml'ку, да и рисунки еще, накладно получается. В принципе можно хранить одну fb2'шку а по обращению получать файл, задержка небольшая, пару секунд и подождать можно (это на нетбуке, на десктопе преобразование выполняется только влет). И тут мне вспомнилось что существует такая вещь как Data Uri, так почему бы не использовать ее и не встроить рисунки прямо в итоговую xhtml'ку. Конечно размер вырастет, но ведь мы получаем xhtml'ку только посмотреть когда нужно, к тому же если такой xsl файл получить то можно будет fb2'ки нормально в браузере читать.
И вот я начал копаться в FB2_2_xhtml.xsl файле.
Сразу видно причину почему пропали рисунки
<xsl:template match="fb:image">
<div align="center">
<img border="1">
<xsl:choose>
<xsl:when test="starts-with(@xlink:href,'#')">
<xsl:attribute name="src"><xsl:value-of select="substring-after(@xlink:href,'#')"/></xsl:attribute>
</xsl:when>
<xsl:otherwise>
<xsl:attribute name="src"><xsl:value-of select="@xlink:href"/></xsl:attribute>
</xsl:otherwise>
</xsl:choose>
</img>
</div>
</xsl:template>


в данном случае просто вырезается # перед рисунком. И предполагается что рисунки будут лежать рядом.
После некоторого шаманства получился следующий код

<xsl:when test="starts-with(@xlink:href,'#')">
<xsl:attribute name="src">
<xsl:text>data:</xsl:text>
<xsl:variable name="href" select="substring-after(@xlink:href,'#')" />
<set variable="href" expression="substring-after(@xlink:href,'#')"/>
<xsl:value-of select="//fb:binary[@id=$href]/@content-type" disable-output-escaping="yes" />
<xsl:text>;base64,</xsl:text>
<xsl:value-of select="//fb:binary[@id=$href]" disable-output-escaping="yes"/>
</xsl:attribute>
</xsl:when>


Почему то простая конструкция
<xsl:variable name="href" select="substring-after(@xlink:href,'#')" />


у меня не захотела задавать переменную, она не виделась в xpath выражении, после дополнительного определения
<set variable="href" expression="substring-after(@xlink:href,'#')"/>
все заработало как нужно.

Также внес небольшие изменения касающие вывода названия книги сверху
<h4 align="center">
<xsl:value-of select="fb:description/fb:title-info/fb:book-title"/>
</h4>

А также вывода обложки

<xsl:for-each select="fb:description/fb:title-info/fb:coverpage/fb:image">
<xsl:call-template name="image"/>
</xsl:for-each>


предварительно исправив <xsl:template match="fb:image"> на <xsl:template match="fb:image" name="image">
Возможно стоит перенести содержание в конец, но в принципе меня и так все устраивает.

Получившийся файл можно взять здесь bit.ly/1JOIvz

P.S. пока искал в нете подходящее решение наткнулся на rusec.livejournal.com/11740.html :)

Ну и касательно fb2 читалки под линуксом не могу процитировать сообщение на которое наткнулся на лоре
Нашел для себя отличный ридер для fictonbook:
«zcat book.fb2.zip|xsltproc FB2_2_txt.xsl -|less -s»
;)

juick.com/demyan/70753



P.P.S. надеюсь это кому нибудь пригодилось. :)
Tags:xmlxhtmldata:urifb2xslt
Hubs: XSLT
Total votes 38: ↑37 and ↓1 +36
Views7.7K

Comments 5

Only those users with full accounts are able to leave comments. Log in, please.