An introduction to DocBook, a flexible markup language worth learning

DocBook is easy to learn, easy to write, and does things other text markup languages can't do.
745 readers like this.
5 trends in open source documentation

Internet Archive Book Images. Modified by Opensource.com. CC BY-SA 4.0

Computers were first invented to do math, and they do it really well. But it didn't take long for users to repurpose their futuristic calculators into fancy, dynamic typewriters. Now human-readable text drives computing, so it's important to choose the right format for the text you write.

DocBook is an XML schema. XML is an extensible markup language a lot like HTML. It's truly ubiquitous, but you may know it by RSS or Atom, the Open Document formats of LibreOffice and Apache OpenOffice, Inkscape and the SVG file format, and much more. In fact, it's safe to say that if you own a computer or mobile device, there's XML on it.

This is what it looks like in its raw form:

 <chapter>
<title>My title goes here</title>

<para>
 Paragraph text goes here.
</para>

<section>
 <title>A section title</title>

<para>
 More paragraph text. Some in <emphasis>italics</emphasis>.
</para>
</section>
</chapter>

DocBook itself is easy to learn and easy to write, and it's also one of the most flexible formats available. What other formats, like Markdown and reStructured Text lack, DocBook provides. And what DocBook doesn't provide is possible through generic XML.

But why bother learning DocBook in a time when simpler alternatives exist? Why bother with a markup language at all when you can instead impose a little structure to your otherwise plain text and end up with highly portable, computer- and human-readable data?

Settle in. All will be revealed.

Fail faster

A distinct difference between working in simpler formats and working in DocBook is that DocBook tells you when you get something wrong. Many other formats, like Markdown and HTML, fail silently. And usually that feels good, because the result is that your document is rendered. You press the Enter key and your document gets processed by whatever parser or processor it requires for conversion, and you're done. What a great feeling.

A distinct difference between working in simpler formats and working in DocBook is that DocBook tells you when you get something wrong.
The reality of failing silently, though, is that it still failed. You might have gotten output, and most of it might look just fine, but what about the error that wasn't caught? Maybe it renders something incorrectly, but if it's buried in page 42 of a 200-page document, when will you notice? Maybe the error rendered correctly in the web version of your document, but incorrectly for the print version.

DocBook, like all XML, is famously strict. If you, for instance, place a <para> after you've closed your <chapter>, then your document build fails, and it generally fails verbosely. Because DocBook is XML, you can even run your source through xmllint to find errors early.

Experiencing errors is never easy. It's not fun to watch your work fizzle out in a pool of illegal tags and syntax errors instead of building into a beautifully rendered EPUB, webpage, or PDF. To get around that disappointment, most processors accept an option to temporarily ignore errors, such as --skip-validation, but ultimately failure is important. Failure identifies imperfections in your source and protects you from unpleasant surprises in your product.

Easier than it looks

DocBook sometimes has a reputation for being hard to learn. I have found that more often it's not DocBook, but the unique tool chains people build around it, that have the steep learning curve.

Compared to HTML, DocBook's tags are self-describing. Do you want to write an article or a book? Start with either the <article> or <book> tag, respectively. Start a new chapter in a book or a new section in an article with <chapter> or <section>, respectively. Start a paragraph with <para>, an ordered list with <orderedlist>, enter a list item with <listitem>, and so on.

Compared to Markdown and AsciiDoc, DocBook appears complex, but if you consider all the rules that aren't intuitive in structured text, DocBook's rules don't seem so bad.

Learning syntax from the original Markdown spec was often a process of trial and error, followed by a series of desperate internet searches, which meant wading through all the different Markdown flavors and parsers for the best applicable candidate for a correct answer. CommonMark, a project dedicated to defining a more arduous and strict specification, has helped, but users are often lulled into a false sense of security by how easy it is to learn the basics, only to find that achieving advanced results introduces a surprise learning curve.

Luckily, Markdown accepts HTML as a fallback markup option, and there are several tools and Markdown variants out there to make up for what the original spec lacks. Even so, if you're writing complex documents for several different output targets, it may not be as easy as it looks in all the "learn Markdown in just 15 minute"-style blogs.

The logic flow to learn something new in DocBook tends to be consistently simple:

  1. Go to the DocBook site.
  2. Find an appropriate tag in the master list.
  3. Refer to the tag's documentation to find out how to correctly use it.

That's all there is to it. It's about the same as learning HTML: learn the basics in the first few minutes, and keep a reference handy to learn more as needed.

Depending on how much you know about XML, there can be a few surprises, but the DocBook website clearly defines valid parent and child relationships for each and every tag, and each entry for each tag provides big blocks of examples.

Semantics

Finally, DocBook is important because it provides data about your data. DocBook tags aren't meant to dictate a style over your content, but to classify the information you are trying to convey. Like HTML and CSS, styling DocBook comes later, and it's completely malleable. DocBook tags provide semantic meaning to your words.

Semantics might not seem that important to you now, but here are two great examples of times that metadata became truly important in the real world:

  • Before mobile phones existed, nobody on the internet would have ever thought that a telephone number would ever need a <tel> tag. If anything, surely an <em> or a <strong> tag would do. And then mobile phones happened, and people all over the world were browsing the internet on the same device they used to make phone calls, and it was a downright inconvenience not to be able to look up a company's phone number and click on it to make the call.
  • A major phone company in New Zealand had been called Telecom for years. When it rebranded as Spark, the word telecommunication appeared as sparkmunication throughout its entire online documentation due to a find/replace mistake. The glitch was live on its website for several days before the obvious error was noticed and corrected. Better regex would have helped, but it wouldn't have happened at all with DocBook entities or the <trademark> tag.

Classifying the information you write is important now and as technology develops.

Create your first DocBook document the easy way

Here's a quick and easy way to get started with DocBook. This method emphasizes learning DocBook tags and syntax rather than building a complex and flexible tool chain.

  1. Open a text editor. Use whatever text editor you are most comfortable with, as long as it can save plain text files. All the good ones do: Gedit, Geany, Kate, Nano, Jove, Emacs, Atom, and many others.
  2. Open a web browser to DocBook 5.2: The Definitive Guide for reference.
  3. Open another tab in your web browser to the article element reference and scroll to the bottom of the page. Copy the text in the example box and paste it into your text editor.
  4. Use the example text as a template and write something. Some of that example's header is more verbose than you probably need, so here I've trimmed off some of the excess.
    <article xmlns='http://docbook.org/ns/docbook'>
     <info>
      <title>My first docbook document</title>
      <author><personname>
     <firstname>Seth</firstname>
     <surname>Kenlon</surname>
      </personname></author>
      <publisher><publishername>opensource.com</publishername></publisher>
      <pubdate>2017</pubdate>
     </info>
    
     <section id="intro">
      <title>Introduction</title>
      <para>Introductory text goes here.</para>
      </section>
    
     <section id="body">
      <title>Section with a title</title>
      <para>Main body text goes here.</para>
     </section>
    
     <section id="conclusion">
      <title>Conclusion</title>
      <para>Exciting and inspiring conclusion goes here.</para>
     </section>
    </article>

    If you are ever in doubt about whether or not a tag is required, just refer to the tag's documentation. The synopsis section tells you what is required and what is optional. For example, the <section> element specifies that one or more title-related elements are required, but all other tags are optional.

  1. Once you've finished writing, it's time to render your document. There are several XML processors available, but the easiest for beginners is Pandoc. It's one of those "Swiss Army knife" applications that converts almost any kind of text into almost any other kind of text. What makes it especially nice for DocBook is that it has attractive stylesheets by default, while most other processors render very generic output under the assumption that you intend to apply your own XSL stylesheet.

    There are all kinds of potential targets, but the commands are all basically the same:

    $ pandoc --from docbook --to epub3 --output myDocbook.epub myDocbook.xml
    
    $ pandoc --from docbook --to markdown --output myDocbook.md myDocbook.xml
    
    $ pandoc --from docbook --to html --output myDocbook.html myDocbook.xml
    
    $ pandoc --from docbook --to latex --output myDocbook.pdf myDocbook.xml

    And that's all there is to it. The more you write in DocBook, the more tags and attributes you learn, and eventually you'll probably find it hard to go back to a less explicit format.

PDF render

opensource.com

Advanced DocBook, with style

Pandoc makes DocBook as easy as HTML, but XML is flexible, so if you need to, you can customize how you build your DocBook documents.

The default DocBook render from most processors (aside from Pandoc) looks a little something like this:

Default PDF render

opensource.com

It's professional, but painfully so. Still, it's an important foundation upon which additional styles can be applied.

HTML and EPUB output

If your target involves HTML, you can continue to use Pandoc, instructing it to use your custom CSS.

$ pandoc --from docbook --to html \
--css=myStyle.css \
--output myDocbook.html myDocbook.xml

$ pandoc --from docbook --to epub3 \
--epub-stylesheet=myStyle.css --epub-cover-image=cover.jpg \
--epub-embed-font=fonts/foo.ttf --epub-embed-font=fonts/bar.ttf \
--output myDocbook.epub myDocbook.xml

The end result is dynamic, lightweight, modern, and as attractive as you make it.

PDF and print output

Rendering to PDF for digital distribution or printing relies either on LaTeX or XSL. I have yet to learn LaTeX, so I choose XSL, but if you're a LaTeX user, you can use Pandoc with custom templates. Otherwise, here's a brief introduction to XSL and the xsltproc command.

XSL is the eXtensible Stylesheet Language and is the CSS of the XML world. If you install DocBook from your Linux distribution or from the DocBook website, you are installing all the default DocBook stylesheets. These serve as the fallback styles whenever you use a tool like xsltproc or xmlto.

If you cannot (or choose not to) install DocBook, you can point to the stylesheets manually in your xsltproc command.

Building a PDF with xsltproc is a two-step process. First, you must generate the .fo file, which is a combination of your XML and your XSL, translated into XSL-FO (formatting objects) markup. Then you process the .fo file with Apache FOP, a Java application that converts formatting objects to PDF.

$ xsltproc --output tmp.fo myDocbook.xml

$ fop tmp.fo myDocbook.pdf

An easy modification to make when just getting started with styling DocBook is your font choice. Fonts are easy to change and make a noticeable difference in your end product.

  1. The first step in adding to the default style is editing an external stylesheet. For font detection, Then create a file called fonts.xml and enter this text:
    <fop version="2.0">
     <renderers>
    <renderer mime="application/pdf">
     <fonts>
      <directory recursive="true">/absolute/path/to/your/system/fonts</directory>
      <auto-detect/>
     </fonts>
    </renderer>
     </renderers>
    </fop>

    This registers all the TTF fonts in your personal or system fonts directory. You don't have to point it to standard font directories, but it must be an absolute, not relative, path.

  2. The next step when modifying a style is to set your new style option so that your processor knows what it is. There are two ways to make a change to XSL parameters. You can set a parameter dynamically as part of your xsltproc command, or you can make the change in an additional stylesheet.

    I use both methods, depending on the gravity of the change. For simple styles that I change often, like page size (sometimes I need A4, other times US Letter), fonts, and so on, I pass parameters as part of my command. That way I can change them quickly and easily and independently of my custom stylesheets. To set fonts:

    $ xsltproc --string-param body.font.family "League Gothic" \
    --output tmp.fo \
    myDocbook.xml

    A list of valid parameters can be found at DocBook XSL Stylesheets User Reference: Parameters.

  3. To output to PDF, tell FOP to register your fonts with your fonts.xml file:
    $ fop -c fonts.xml tmp.fo myDocbook.pdf
    

XSL stylesheet

For styles less likely to change based on printer requirements, page size, or mood, I place rules in a custom XSL template. XSL templates can get very complex, so making minor adjustments and learning over time is a good approach.

Here's a simple example.

A common visual cue seen in printed books is an admonition, like a note, tip, or warning, printed over a background color to let the reader know it is separate from the current narrative but still important to the topic. Admonitions are distinct elements in DocBook, so they're relatively simple to style.

The process is similar to styling fonts.

First, create a new file called mystyle.xsl in your working directory. Edit it so that it contains this heading:

<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
 <xsl:import href="https://opensource.com/usr/share/xml/docbook/xsl-stylesheets-1.78.1/fo/docbook.xsl"/>

The xsl:import line must point to the stylesheet on your system, whether you have installed it or you are using it from a nonstandard location in your home directory.

In this same file, enter some style rules:

<xsl:template match="note">
 <xsl:variable name="id">
<xsl:call-template name="object.id"/>
 </xsl:variable>
 <fo:block xmlns:fo="http://www.w3.org/1999/XSL/Format"
   space-before.minimum="0.8em"
   space-before.optimum="1em"
   space-before.maximum="1.2em"
   start-indent="0.25in"
   end-indent="0.25in"
   padding-top="6pt"
   padding-bottom="2pt"
   padding-left="4pt"
   padding-right="4pt"
   background-color="#ffffbd">
<xsl:if test="$admon.textlabel != 0 or title">
 <fo:block xmlns:fo="http://www.w3.org/1999/XSL/Format"
   keep-with-next='always'
   xsl:use-attribute-sets="admonition.title.properties"
   font-family="League Script Thin"
   color="#348fdf"
   font-weight="bold">
<xsl:apply-templates select="." mode="object.title.markup"/>
 </fo:block>
</xsl:if>
            
<fo:block xmlns:fo="http://www.w3.org/1999/XSL/Format"
   xsl:use-attribute-sets="admonition.properties"
   font-family="League Gothic">
  <xsl:apply-templates/>
</fo:block> 
 </fo:block>
 </xsl:template>
</xsl:stylesheet>

This creates a template in your stylesheet for all elements that match the note. Whenever the XSL processor finds a <note> tag, it drops in the XSL-FO blocks to describe how elements are to be printed (whether the paper is digital or physical).

Apply the styles with xsltproc and output to PDF to FOP:

$ xsltproc --string-param body.font.family "League Gothic" \
mystyle.xsl --output tmp.fo \
myDocbook.xml

$ fop -c fonts.xml tmp.fo myDocbook.pdf

Get the output:

Styled PDF render

opensource.com

The syntax is nowhere as terse or simple as CSS syntax. However, simple styles follow the same format:

  1. Create an <xsl:template> block for the tag that you want to affect.
  2. Look up the available XSL attributes at DocBook XSL Stylesheets User Reference.
  3. Set the attributes you want to apply in a <fo:block>.

Like CSS, getting to know all your options takes time and practice, but once you get the hang of it, it's simple. More complex XML gets you more complex rules with dependencies, variables, conditionals, and more. For an exhaustive overview, see the definitive DocBook XSL: The Complete Guide website.

Using DocBook

DocBook was invented for tech writers, and many of its tags reflect that. However, I use DocBook for everything, whether it's tech writing, fiction, or RPG design, it's a powerful, industry-strength system.

This doesn't mean that there's no place in the world for Markdown or org-mode or other text formats. If I'm writing a README file or a short note to myself, DocBook is overkill, because the source document is also meant to be the final delivery format. In other words, where I would historically have used plain text, I use Markdown because Markdown's structure is a vast improvement over unstructured text.

I also use Markdown as an intermediate format. I usually write Opensource.com articles in DocBook and then output to Markdown so that a site editor can easily review and convert my work. Going directly from DocBook to HTML is great if you're running your own site and can govern what tags, classes, and IDs get used, but Markdown serves as an excellent intermediate step when you temporarily want to ignore your source metadata and just deliver the written words.

For everything else, DocBook is a great solution. Give it a try, and you'll never look at word processors, text, or XML the same way again.

Seth Kenlon
Seth Kenlon is a UNIX geek, free culture advocate, independent multimedia artist, and D&D nerd. He has worked in the film and computing industry, often at the same time.

9 Comments

Thanks for this article, Seth. It's been a while since I've worked with DocBook and, to be honest, I'm kind of missing it. I might have to dust off the old skills ...

Years ago, I took a job that had me working in rST and markdown. Three years was long enough to assure me that Docbook was the better choice. I'm happy to report that my current job has me back in Docbook.

I'd rather spend 8 hours for one day getting my XSL right than spend three hours every day for the rest of my life hacking around rST and markdown syntax exceptions.

When I was using DocBook a lot several years ago, I went through a phase where I wrote and often published everything with it. Then, I concluded that it's overkill for shorter works like articles and blog posts and even letters (yes, I used it for letters!). For anything short, I use Markdown or HTML. But DocBook is definitely one of my two choices for reports, books, and longer bits of documentation.

In reply to by sethkenlon

Interesting article, thank you.
I maintain church service books, which need quite complex layout, so I have been writing them directly in epub. I then process these to PDF for printing, but also output them for electronic books.
Looking at the article, it seems I may gain some advantage from DocBook, using different toolchains for the various formats.
My main problem with using epub is that I'm the only one with the skills to maintain them. DocBook, for all it's comprehensiveness, and verbosity, appears very understandable. One little complexity that I have to manage is 4-part music, at the moment I use Lilypond mark-up for that, and embed the resulting images.
Any thoughts would be helpful.

Like TeX, it seems that DocBook does best with pure text output. Working with graphics and trying to place them precisely is challenging as far as I can tell.
Scribus, of course, is designed for layout at great precision, and is wysiwyg. It also has Render frames, which can make use of Lilypond markup, TeX, and others.

I have tried Scribus, I found it, like most wysiwyg desktop applications, almost unusable, sorry. It's targeted on PDF, my target is Print and Electronic Media. I also found the documentation, for instance the wiki, very out of date.
But thank you for the suggestion.

In reply to by Greg P

I've found that it's easier to work with graphics in DocBook than it is in TeX or LaTeX. As with anything, it's all about what you need to do. In those rare instances I need to create a shorter document with a more complex layout, I turn to Scribus. But when I need to output a longer, nicely-typeset document I'll turn to LaTeX or DocBook.

In reply to by Greg P

Depends on what you're trying to do. Placing graphics isn't difficult if you're just inserting graphics into the flow of text or block elements. However, if you're doing something like fancy layout design, like partly transparent background images or rounded graphics that you want to wrap text around, or even text on paths, then docbook is likely not the best option.

I use scribus for projects that require fancy layouts. I use docbook for the docs that I want to be able to work on without a GUI, and that many other people would do in a word processor. I don't consider it a layout or design schema...maybe some day, when I'm much much better with XSL...

In reply to by Greg P

Creative Commons LicenseThis work is licensed under a Creative Commons Attribution-Share Alike 4.0 International License.