Generating Apple HelpViewer documents from DocBook

July 12, 2009 Off By leigh

Apple’s HelpViewer application is quite nice for users to read documentation for their application. The help documentation for each application is authored in HTML, with a couple of extra META tags.

However this is less than ideal if you also want to provide a printed version of the documentation (i.e. PDF), or other file formats, or, as in the case of the MusicKit, we wanted to adopt a common documentation format, without having some documentation authored in RTF, some in HTML etc.


Apple’s HelpViewer application is quite nice for users to read documentation for their application. The help documentation for each application is authored in HTML, with a couple of extra META tags.

However this is less than ideal if you also want to provide a printed version of the documentation (i.e. PDF), or other file formats, or, as in the case of the MusicKit, we wanted to adopt a common documentation format, without having some documentation authored in RTF, some in HTML etc.

The DocBook format standard has been around for many years now. This format is a document type definition (DTD) for SGML or XML aimed at documentation markup, in particular for software documentation. It has evolved to be a good way to separate the style from the content of documentation. I had converted most of the documentation of the MusicKit from RTF to SGML DocBook many years ago, but the application documentation lagged behind because it required some special formatting for HTML that was usable with Apple’s HelpViewer.

I had produced a DocBook DSSSL style sheet that produced the documentation for AlphabetSoup several years ago, but at the time, it was too difficult to produce a generalised solution for all MacOS X applications. Anyway, my LISP/Scheme chops have improved since then, plus my recklessness in delving into DSSSL.

So with MusicKit_HelpViewer.dsssl, any DocBook SGML file can be converted to a set of HTML pages, arranged in the correct hierarchy (a top level HTML introductory file, with all other HTML and image files in subdirectories). The Apple HelpViewer special tags are now automatically generated. This is incorporated into the standard MusicKit Xcode build process with a script to run openjade, an open source DSSSL interpreter.

For example, to build the documentation for the ScorePlayer application of the MusicKit:

# Run openjade to convert SGML to HTML
mkdir -p $TARGET_BUILD_DIR/$UNLOCALIZED_RESOURCES_FOLDER_PATH/English.lproj/scoreplayerhelp/Pages
if [ -x `which openjade` ]; then
    cd $TARGET_BUILD_DIR/$UNLOCALIZED_RESOURCES_FOLDER_PATH/English.lproj/scoreplayerhelp
    PATH=$PATH:/sw/bin/
    openjade -t sgml -ihtml -d $SRCROOT/Documentation/SGML/MusicKit_HelpViewer.dsssl\#html 
        $SRCROOT/Applications/ScorePlayer/Help/English.lproj/ScorePlayer.sgml
else
    echo Missing openjade so skipped building ScorePlayer Help from SGML.
fi
exit 0

Note that I set the PATH since I assume openjade is installed using fink. I also assume all subsequent HTML pages are stored in the Pages subdirectory, and that there is a CSS file in top level Help directory as well as in the Pages subdirectory. In Xcode, the input file is specified to be

$(SRCROOT)/Applications/ScorePlayer/Help/English.lproj/ScorePlayer.sgml

and the output file is specified as:

$(TARGET_BUILD_DIR)/$(UNLOCALIZED_RESOURCES_FOLDER_PATH)/English.lproj/scoreplayerhelp/scoreplayer.html

which then only rebuilds the documentation if the ScorePlayer.sgml file changes.

One compromise is that the directory name the generated HTML files reside in must be lowercase and must match the ID attribute for the ARTICLE element in the DocBook file. This is because HelpViewer requires the path to the icon file to be specified relative to the Resources directory, not to the Help directory, so the Help directory must be stored in the generated HTML. The solution was to enforce the ID tag of the ARTICLE element to match the Help directory. The attribute name is returned by openjade in uppercase, which I suspect is a limitation of using SGML, whereas I believe XML preserves the case of attribute strings. I therefore fold the attribute string to lowercase.

Of course, DSSSL is out of favour nowdays, with preferences to XSL. Having recently spent some time hacking XSL as part of IRCAM‘s contribution to the Quaero project, I suspect it’s possible to generate similar results in XSL, but I’m sure it wouldn’t be as fun to do.