xmlxsltdocbookdocbook-5docbook-xsl

using font awesome in Docbook generated HTML


What steps should I take in creating a placeholder in docbook xml files that will use font awesome fonts in the generated HTML output. Looking for xslt examples that use font awesome fonts in HTML output generated from DocBook.


Solution

  • Hopefully this answer isn't tl;dr. If you would rather me break this out into 3 separate answers, please let me know.

    Option 1

    The first option is to use the HTML markup in the entity declaration like I first mentioned in the comments.

    Pros

    Cons

    What you'll need to do:

    1. Change your entity declarations to look like this:

      <!ENTITY fa-birthday-cake "<i class='fa fa-birthday-cake' xmlns=''></i>">
      

      This is slightly different from what I had in my first comment. I added an empty namespace so that the i element wasn't automatically in the default namespace.

    2. Add the link to the font-awesome css in the head. (I have it pointing to font-awesome locally.)

      <link rel="stylesheet" href="font-awesome-4.3.0/css/font-awesome.min.css"/>
      

      For testing I modified frameworks/docbook/xsl/html/profile-docbook.xsl. I added the link around line 460 in the match="*" mode="process.root" template.

    3. Add the template to match the i element so it doesn't get replaced.

      <xsl:template match="i">
          <xsl:copy-of select="."/>
      </xsl:template>
      

    Example...

    Docbook Input

    <!DOCTYPE section [
    <!ENTITY fa-birthday-cake "<i class='fa fa-birthday-cake' xmlns=''></i>">
    ]>
    <section xmlns="http://docbook.org/ns/docbook" version="5.0">
        <title>Section Template Title</title>
        <para>birthday cake: &fa-birthday-cake;</para>
    </section>
    

    HTML Output (using DocBook HTML transformation scenario)

    <html>
        <head>
            <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
            <link rel="stylesheet" href="font-awesome-4.3.0/css/font-awesome.min.css">
            <title>Section Template Title</title>
            <meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
        </head>
        <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
            <div class="section">
                <div class="titlepage">
                    <div>
                        <div>
                            <h2 class="title" style="clear: both">
                            <a name="d56e3"></a>Section Template Title</h2>
                        </div>
                    </div>
                    <div></div>
                    <hr>
                </div>
                <p>birthday cake: <i class='fa fa-birthday-cake'></i></p>
            </div>
        </body>
    </html>
    

    Rendererd HTML

    Rendered HTML

    Option 2

    The second option is to use font awesome class in the entity declaration and use the symbol element, with a special role attribute, to hold the reference.

    Pros

    Cons

    What you'll need to do:

    1. Change your entity declarations to look like this:

      <!ENTITY fa-birthday-cake "fa-birthday-cake">
      
    2. Add the link to the font-awesome css in the head. (I have it pointing to font-awesome locally.)

      <link rel="stylesheet" href="font-awesome-4.3.0/css/font-awesome.min.css"/>
      

      For testing I modified frameworks/docbook/xsl/html/profile-docbook.xsl. I added the link around line 460 in the match="*" mode="process.root" template.

    3. Add the template to match the symbol element with the 'fa' role and output the i. (d is bound to the http://docbook.org/ns/docbook namespace in profile-docbook.xsl)

      <xsl:template match="d:symbol[@role='fa']">
          <i class="fa {.}"></i>
      </xsl:template>
      

    Example...

    Docbook Input

    <!DOCTYPE section [
    <!ENTITY fa-birthday-cake "fa-birthday-cake">
    ]>
    <section xmlns="http://docbook.org/ns/docbook" version="5.0">
        <title>Section Template Title</title>
        <para>birthday cake: <symbol role="fa">&fa-birthday-cake;</symbol></para>
    </section>
    

    HTML Output (using DocBook HTML transformation scenario)

    <html>
        <head>
            <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
            <link rel="stylesheet" href="font-awesome-4.3.0/css/font-awesome.min.css">
            <title>Section Template Title</title>
            <meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
        </head>
        <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
            <div class="section">
                <div class="titlepage">
                    <div>
                        <div>
                            <h2 class="title" style="clear: both">
                            <a name="d56e3"></a>Section Template Title</h2>
                        </div>
                    </div>
                    <div></div>
                    <hr>
                </div>
                <p>birthday cake: <i class='fa fa-birthday-cake'></i></p>
            </div>
        </body>
    </html>
    

    Rendererd HTML

    Rendered HTML

    Option 3

    The third option is to switch to XSLT 2.0 and use an xsl:character-map.

    Pros

    Cons

    What you'll need to do:

    1. Keep your entity declarations looking like this (based on your other question https://stackoverflow.com/questions/30055181/how-do-i-insert-fonts-as-an-entity-in-docbook):

      <!ENTITY fa-birthday-cake "&#xf1fd;">
      
    2. Add the link to the font-awesome css in the head. (I have it pointing to font-awesome locally.)

      <link rel="stylesheet" href="font-awesome-4.3.0/css/font-awesome.min.css"/>
      

      For testing I modified frameworks/docbook/xsl/html/profile-docbook.xsl. I added the link around line 460 in the match="*" mode="process.root" template.

    3. Change the xsl:stylesheet version to 2.0.

    4. Import the xsl:character-map.

      <xsl:include href="font-awesome.xsl"/>
      

      I've included an example "font-awesome.xsl". I have the complete version based on the font-awesome cheatsheet today (2015-05-06). Adding the entire contents pushes my answer over the character limit; let me know if you need it.

      <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
          <xsl:character-map name="fa">
              <xsl:output-character string="&lt;i class='fa fa-birthday-cake'&gt;&lt;/i&gt;" character="&#xf1fd;"/>
          </xsl:character-map>
      </xsl:stylesheet>
      
    5. Reference the character map (with use-character-maps) in the xsl:output.

      <xsl:output method="html" encoding="ISO-8859-1" indent="no" use-character-maps="fa"/>
      
    6. Possible additional changes.

      Like mentioned in the "cons" section, you might need to make some changes to the docbook stylesheets depending on what processor you use. I used Saxon-HE 9.5.1.3. I did this by duplicating the DocBook HTML transformation scenario and changing the processor.

    Example...

    Docbook Input

    <!DOCTYPE section [
    <!ENTITY fa-birthday-cake "&#xf1fd;">
    ]>
    <section xmlns="http://docbook.org/ns/docbook" version="5.0">
        <title>Section Template Title</title>
        <para>birthday cake: &fa-birthday-cake;</para>
    </section>
    

    HTML Output (using the modified DocBook HTML transformation scenario)

    <html>
        <head>
            <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
            <link rel="stylesheet" href="font-awesome-4.3.0/css/font-awesome.min.css">
            <title>Section Template Title</title>
            <meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
        </head>
        <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
            <div class="section">
                <div class="titlepage">
                    <div>
                        <div>
                            <h2 class="title" style="clear: both">
                            <a name="d56e3"></a>Section Template Title</h2>
                        </div>
                    </div>
                    <div></div>
                    <hr>
                </div>
                <p>birthday cake: <i class='fa fa-birthday-cake'></i></p>
            </div>
        </body>
    </html>
    

    Rendererd HTML

    Rendered HTML