Friday, January 25, 2019

Migrating Various Document Formats to DITA

Share to Facebook Share to Twitter Email This Share on Google Plus Share on Tumblr

Most companies do not start new DITA-based projects from scratch. They already have content written in various other formats and somehow they need that content converted to DITA. In this blog post, I will offer some conversion advice depending on the format of your current project.

Migrating DocBook content to DITA.

Because DocBook content is XML, migrating it to DITA is quite straight forward:
  1. You first convert the DocBook document to a single large DITA composite file and you can do that with the predefined transformation scenario bundled with Oxygen called DocBook to DITA.
  2. There is a utility XSLT stylesheet on the Oxygen XML GitHub account that can convert a DITA composite to a DITA map with separate DITA topic files:

Migrating Microsoft Word content to DITA

The Oxygen XML User Manual has a detailed topic enumerating the possibilities to convert Microsoft Word content to DITA:

Migrating Excel content to DITA

You can use Oxygen's Smart Paste functionality to copy content from an Excel spreadsheet and paste it inside an opened DITA topic. Also, as an alternate possibility, the Oxygen Resources Converter add-on was updated to be able to batch convert Excel to DITA:

Migrating LibreOffice content to DITA

LibreOffice documents can be saved in Word format, and once you do that, you can convert the Word content to DITA as described above. Alternatively, you can save the LibreOffice documents to DocBook and then apply the DocBook to DITA conversion technique described above.

Migrating Google Docs to DITA

You have three possibilities to convert Google Docs to DITA using Oxygen:
  • Copy/Pasting from Google Docs to a DITA Topic opened in Oxygen in the Author visual editing mode should work and convert the pasted content to DITA.
  • Save the Google document as OpenDocumentFormat (ODF) then save the ODF document as DocBook with Libre Office, then apply the DocBook to DITA transformation scenario shipped in Oxygen to convert DocBook to DITA.
  • Save the Google document as HTML then use the Oxygen batch converter add-on to convert it to DITA:

Migrating Markdown content to DITA

The DITA Open Toolkit publishing engine bundled with Oxygen allows you to reference Markdown files directly in a DITA map and either publish them directly or export the Markdown files to DITA one by one: If you want to convert multiple Markdown documents at once, you can use the Oxygen Resources Converter add-on:

Migrating HTML content to DITA

Using Oxygen's Smart Paste functionality, you can open the HTML documents in a web browser, then copy the contents and paste it in a DITA topic opened in Oxygen's Author visual editing mode. If you want to convert multiple HTML files, you can use the Oxygen Resources Converter add-on:

Migrating unstructured FrameMaker to DITA

There is a FrameMaker plugin that can be used for this type of conversion:

Migrating MadCap content to DITA

Some recent MadCap versions seem to have facilities to export content directly to DITA. Otherwise, you will need to convert XHTML content to DITA with a custom XSLT stylesheet to preserve variable references.

Migrating other formats to DITA

You may find third-party applications (like Pandoc) that can convert your content to HTML or to some kind of XML format like DocBook. Once you have HTML or DocBook content, you can convert them to DITA using the advice above.

Wednesday, May 02, 2018

Translating your DITA Project

Share to Facebook Share to Twitter Email This Share on Google Plus Share on Tumblr

Usually when working with a DITA-based project you can either store the project contents using a Content Management System (CMS) or some open-source version control system like Git or SVN. CMSs usually come with their own translation support so this blog post is mostly for end users who use Git or SVN to store and collaborate on their DITA project.

Choosing a Translation Agency

Ideally your translation agency should be able to handle DITA content directly, without you needing to convert the DITA to some intermediary format. This means that you will have the full benefit of DITA reuse features to minimize translation costs.

As a very important rule, if you plan to translate your project you should get in touch with a DITA-aware translation agency very early in your project's timeline. Reliable translation agencies that translate DITA content directly (for example WHP) usually need to have a preliminary discussion with you about how the project is structured, what terms need to be skipped when translating, how various measuring units are translated, content reuse, taxonomy, and the handling of screenshots that appear in your DITA content. So the way that you write your DITA content will be influenced by your discussion with the translation agency.

If your translation agency does not directly handle DITA content, there are commercial tools that can be used to convert DITA to XLiff:

Optimizing Content for Translation

In general, there are three main principles to take into account when writing DITA content that will be translated at some point:
  1. Use a controlled vocabulary (usually the Simplified Technical English vocabulary).
  2. Avoid reusing inline elements other than product names. The following DITA Users List discussion describes the reasons for this:
  3. Avoid profiling/filtering content at inline level. For the same reasons as (2).
You can read more about this in the following article:

General DITA Project Structure

Usually you need to keep a folder that contains all your DITA maps/topics in English and have separate folders for other languages with equivalent DITA topics translated in that specific language. This article could be useful:

General Translation Workflow

When translating DITA content, the most common process involves these steps:
  1. You create your content in the primary language using a DITA authoring tool (Oxygen XML Editor).
  2. Before each release, you gather all the DITA topics that have been changed and need to be translated. The Oxygen Translation Package Builder plugin might be handy for this.
  3. Send a copy of the relevant DITA files to the translation agency (known also as "localisation service provider").
  4. Receive translated DITA content back from the translation agency and integrate it in each language-specific project folder.

Publishing your Translated Content

All your translated DITA maps and topics should have the xml:lang attribute set with the appropriate value on the root element. Besides the actual translated content, the published output may contain various static texts like the word Table followed by the table number, Figure following by the number or Note which appears before each DITA <note> content. The DITA Open Toolkit has support for a number of languages for the HTML-based outputs and for the PDF-based outputs. But you can also add support for other languages: There is also a specific topic which describes how to add a new language to the Oxygen-specific WebHelp Responsive output:


So who is responsible for a bad translation that may produce damage to a client following a set of mis-translated steps? From my discussions with translation service providers, the translation agencies do not assume any liability for incorrectly translated content. Usually a company that needs to translate their DITA content in multiple languages has regional headquarters in various countries and somebody from the company's regional headquarters would be responsible to review and accept the translated content as appropriate.

This concludes my DITA translation overview. As we do not translate the Oxygen User's Manual in various languages, our internal knowledge of translating DITA content is quite limited so any feedback on this small article is welcomed.

Tuesday, March 27, 2018

Guided DITA Authoring Solution Overview

Share to Facebook Share to Twitter Email This Share on Google Plus Share on Tumblr

We've had past blog posts about how Oxygen can be used to impose various editing behaviors for your team. In this blog post, we are going to try to bring all of these solutions together in a comprehensive overview.

Learning to Work with DITA and Oxygen

You can find useful links for learning to edit DITA using Oxygen in this previous blog post:

Migrating to DITA

There are multiple reasons why you would want to migrate from unstructured content to structured:

This older blog post details some possibilities of migrating Word documents to DITA: You also have ways to migrate from XML-based standards (like DocBook or XHTML to DITA) using a set of predefined transformation scenarios.

Restricting the Visual Editing Experience

The entire visual editing experience using the Author editing mode in Oxygen is CSS driven. Oxygen has support for defining various CSS layers that can be applied when editing DITA content. For example, if you choose to create a Lightweight DITA topic in Oxygen, it has a special editing layer that allows it to be edited with a combination of buttons, hints, and form controls. This blog post details how a custom CSS used for editing can be created and shared with others:

Implementing Your own Style Guide

Let's say you are a team of technical writers collaborating on a DITA-based project and suppose that you have your own various best practices in regards to which elements to use and when to use them. So, at some point you gather a set of HTML resources that explain how various DITA elements should be used, you store them on an internal server, and you want all your team members to have access to that set of HTML resources directly from Oxygen. This blog post provides more details and useful links to help you get started:

Imposing Controlled Attribute Values

If you want to impose DITA attribute values that need to be set for profiling or general use, this blog post should cover all you need to know about this:

Imposing Business Rules and Structure Restrictions to the DITA Content

In most cases, instead of relying on people to memorize numerous internal documentation style rules, you can convert many of these rules to Schematron and allow the application to automatically signal the content author when a rule is violated. You can also add quick fixes to show authors various ways to rectify the problem. This blog post contains more details about this: The DITA framework can be extended in order to add new Schematron rules:

Running Batch Validation Checks on all of Your DITA Content

The Validate and Check For Completeness tool available in the DITA Maps Manager view performs a lot of different consistency checks on all your DITA topics. It can also be used to apply Schematron business rules on all of your topics:

Sharing DITA Editing Customizations with Your Team

Most of the custom editing behaviors, toolbar, and menu buttons that are available when editing DITA content are defined in the DITA framework configuration. A framework configuration's general anatomy is described here:

The framework configuration can be shared with all of your team members. For example, here is a way to restrict team members from using certain DITA elements: Furthermore, here is a way to distribute new DITA file templates to your team:

Sharing Global Application Settings with Your Team

Let's say you want all of your team members to enable the automatic spell checker when writing documentation, or you want all of them to use a custom term dictionary or a custom set of learned words. This older blog post offers some hints about how global Oxygen settings can be distributed to your team members:

Collaboration, Content Management, and Version Tracking

All major Component Management Systems (CMSs) have plugins that can be installed in Oxygen to provide access to the CMS: Even if you lack the funds to buy a commercial CMS, there are still plenty of open source version tracking solutions that allow collaboration for a single DITA project: For example, the Oxygen User's Manual is written in DITA and we use a GitHub private repository to collaborate on it:

Allowing Subject Matter Experts to Review Content

Many technical writers are interested in having their content reviewed by the subject matter experts who are directly involved in building the tools. Oxygen has support for change tracking and adding comments directly in the edited content. Subject matter experts do not necessarily need to have the standalone version of Oxygen installed. The Oxygen Web Author is an online editing and reviewing solution that allows them to add comments and propose changes directly in the DITA content by using any device with a web browser (laptop, tablet, phone):

I hope this overview will help you to implement a complete guided authoring experience using Oxygen. As usual, if you have any questions or suggestions, they are welcome.

DITA Publishing Customization Overview

Share to Facebook Share to Twitter Email This Share on Google Plus Share on Tumblr
Oxygen XML Editor publishes DITA content to various output sources using a bundled version of the DITA Open Toolkit (short name: DITA OT) publishing engine. Oxygen versions prior to version 20 come with two DITA OT versions:
  • DITA OT 1.8 located in the OXYGEN_INSTALL_DIR\frameworks\dita\DITA-OT folder.
  • DITA OT 2.x located in the OXYGEN_INSTALL_DIR\frameworks\dita\DITA-OT2.x folder.
while Oxygen version 20 comes bundled only with DITA OT 2.x located in the folder specified above. You can find the exact version of DITA OT bundled with Oxygen by looking in the main menu Help->About at the Frameworks tab.

DITA Open Toolkit Overview

The DITA Open Toolkit is an open source publishing engine that can publish DITA content to various output sources such as XHTML, PDF, or Windows Help (CHM). Since it has a plugin-based architecture, it can be extended with extra plugins that either define new formats for conversion or customize an existing conversion format. You can run the DITA OT from Oxygen using its transformation scenarios or you can run it directly from a command line:

The DITA OT bundled with Oxygen contains more plugins than the standard DITA OT that can be downloaded from the DITA OT official web site. For example, it contains pre-installed plugins for converting DITA content to Word, EPUB, Oxygen WebHelp, or to publish to PDF using CSS to customize the output:

Publishing Customizations (Before you begin)

Some customizations, usually for HTML-based output, can be made simply by creating a custom CSS and they do not involve modifying the DITA OT engine in any way. But most customizations might involve adding a new plugin to the DITA OT. So here are some best practices before you begin your customization:
  1. Copy the bundled DITA OT folder (usually OXYGEN_INSTALL_DIR\frameworks\dita\DITA-OT2.x) to a location outside of Oxygen. This will allow you to have full write access to the folder in order to install new plugins:
  2. In the Oxygen Preferences->DITA page, set the default DITA OT distribution to be the external copied one. This will mean that Oxygen will use the external DITA OT for DITA validation and publishing. After doing this, you will be able to upgrade the Oxygen version and benefit from all editing-related improvements without affecting the publishing system.
  3. Share that external DITA OT copy with the rest of the team. If you are using a repository like Subversion or Git for collaboration, you can commit the entire modified DITA OT publishing engine as part of your project. This will allow everybody else in your team to use the official changes that you made for publishing an engine containing. This will also allow you to set up some kind of automatic publishing system using an open-source integration server like Travis.

Customizing the XHTML-based outputs

Usually XHTML-based outputs can be modified by using a custom CSS stylesheet to override various styles. If you edit an XHTML-based transformation scenario in Oxygen, there is a parameter called args.css that can be set to point to your custom CSS and a parameter called args.copy.css that can be set to yes to copy the CSS to the output folder. To know what CSS styles to override, you can use your web browser’s CSS Inspector tools to look at the produced HTML output. The same parameters can be set when publishing from a command line:

You can also create plugins to customize the XHTML-based outputs by adding an extra XSLT stylesheet: for example, A list with all DITA OT XSLT extension points can be found here:

Customizing the Oxygen WebHelp-based output

Oxygen’s DITA OT comes bundled with specific plugins developed by Oxygen that allows publishing DITA content to WebHelp Classic and WebHelp Responsive outputs. Oxygen’s User’s Guide has detailed topics about how to customize these outputs:

Customizing the PDF Classic output

The DITA to PDF output can be customized either by creating a PDF customization folder (in this case the DITA OT folder will not be modified at all) or by creating a PDF customization plugin: There is also a book called DITA For Print that contains details about how to customize various aspects.

Customizing the DITA + CSS to PDF output

In recent versions, Oxygen added a new transformation scenario called DITA Map PDF - WYSIWYG that allows you to use CSS to style the PDF output, lowering the required knowledge for implementing a PDF customization. There is an entire chapter in the Oxygen users manual covering various PDF customization details:

Thursday, January 25, 2018

Composing Author Actions

Share to Facebook Share to Twitter Email This Share on Google Plus Share on Tumblr
Suppose that each time you insert a DITA table in the Author visual editing mode, you want to always have the attributes colsep="1" rowsep="1" frame="all" set on it. The purpose of this post is to create a new DITA-specific action for inserting a table that invokes the current table insertion action and then forces those three attributes to be set on the table element. Here are some steps to accomplish this:
  1. Follow the steps listed in this older blog post to create an extension of the DITA framework:

  2. In the Document Type Association preferences page, edit the DITA framework extension you just created. Go to the Author->Actions tab and create a new action with the ID change.table.colsep. Use the predefined ChangeAttributeOperation to set the (colsep="1" attribute) on the closest table element. The custom action would look like this:

  3. Based on the same idea, create two more new actions called "change.table.rowsep" and "change.table.frame" that will set the rowsep="1" and frame="all" attributes on the closest table, respectively.

  4. Create a new action with the ID insert.table.fixed.attributes and use the predefined ExecuteMultipleActionsOperation to call 4 actions in a row, the original insert.table action ID that inserts the table, followed by the three action IDs that set various attribute values to the inserted table.

  5. Go to the Author->Toolbar tab and in the "Current actions" panel, remove the current "insert.table" action and replace it with the insert.table.fixed.attributes action ID.

  6. When editing a DITA topic, pressing the toolbar action for inserting a table should now call your custom action that sets those three attributes on the inserted table.

Wednesday, January 03, 2018

Sorting glossary lists in a DITA Bookmap

Share to Facebook Share to Twitter Email This Share on Google Plus Share on Tumblr

The idea behind this DITA refactoring action started from this forum post:

Suppose you have a DITA Bookmap that at some point references all of its glossary entries:
                <topicref href="glossary/glossItem1.dita"/>
                <topicref href="glossary/glossItem2.dita"/>
                <topicref href="glossary/glossItem3.dita"/>
                <topicref href="glossary/glossItem4.dita"/>
and you want to have all of these glossary topics sorted alphabetically by title as they appear in the PDF output.

One option for this is to create a PDF customization that automatically sorts the glossary entries no matter what order they were originally specified in the DITA Map.

The other option is to create a custom Oxygen XML Refactoring operation that, when applied on the DITA Bookmap containing the "glossarylist", will sort the glossentries in alphabetical order according to the title of each glossentry.

The following steps will help you achieve this:
  1. Somewhere on disk, create a folder (for example, customRefactor) and add a reference to it in the Oxygen Preferences->"XML / XML Refactoring" page.

  2. In that custom folder, create an XML file (for example, sortGlossentries.xml) that has the following content:

        xmlns="" id="op_tck_rp1_hcb" name="Sort glossentries">
        <description>Sort glossentries.</description>    
        <script type="XSLT" href="sortGlossentries.xsl"/>

    This particular descriptor file contains the name of the operation, its description, and points to an XSLT stylesheet that will be applied to sort the entries in the DITA Bookmap.

  3. In the same folder, create a file called sortGlossentries.xsl with the following content:

    <xsl:stylesheet xmlns:xsl=""
        <xsl:template match="node() | @*">
                <xsl:apply-templates select="node() | @*"/>
        <xsl:template match="glossarylist">
                <xsl:apply-templates select="@*"/>
                <xsl:for-each select="*" >
                    <xsl:sort select="document(@href, .)/*/glossterm/text()"/>
                    <xsl:apply-templates select="."/>

    This particular XSLT processing copies almost all the Bookmap content unchanged. However, the topicrefs in the glossarylist are sorted according to the glossterm titles specified inside each of them.

  4. Restart Oxygen.

  5. Open the bookmap that contains the glossarylist in the Oxygen main editing area, right-click, choose Refactoring and in the Other operations submenu you will find the new Sort glossentries refactoring action. Invoke the action and use the Preview button to check if the sorting is properly done.

Friday, September 15, 2017

Small problems with the DITA standard

Share to Facebook Share to Twitter Email This Share on Google Plus Share on Tumblr

Don't get me wrong, I think that DITA is a great standard for writing technical documentation, it has lots of reuse possibilities and linking potential, and in general, it's well thought out and comprehensive.

Over the years, many of our Oxygen XML Editor clients (or me, personally) have encountered various limitations/quirks in the DITA standard and I will share them below. These complaints are not related at all to the publishing part and I think that some of them will probably be resolved as the DITA standard evolves from one version to another. Also, many of these issues could not be effectively fixed since the DITA standard has strived (and succeeded) to be backward compatible and thus, the issues remain from version to version. So here we go:
  • When I create a DITA specialization, to add a new attribute according to the specification I need to add that attribute to all DITA elements. I think the main idea was that the new attribute is a profiling attribute so it makes sense to be added to all elements, but sometimes you need to funnel this behavior and make the attribute available only on a certain element and still consider the specialization as a valid DITA specialization.
  • The existing xml:lang attribute cannot be used to profile and filter out content. In the past, we had users somehow mixing languages in the same DITA Map and expecting to create output for one language or the other by filtering based on the xml:lang attribute.
  • You cannot easily profile/filter out an entire column from a CALS table. For example, you cannot add a profiling attribute directly to the DITA colspec element to remove entire table columns when publishing. So the alternative is to use a DITA simple table and define the profiling attribute on each of the cells in the column or to perform some kind of output customization based on a magic outputclass attribute set on a certain element in the table.
  • There are too many constraints imposed when writing DITA specializations. Robert Anderson, the DITA OT project manager and OASIS member involved in defining the DITA standard, had two interesting blog posts on this:
  • With most of the material being published for web and with the need to dynamically include media resources (video, audio) in the published HTML content, it's a pity that the DITA standard does not yet have specialized <audio> and <video> elements. Again, we need to rely on the magic outputclass attribute to give semantic to the generic DITA <object> element.
  • Sometimes there are two or more ways of doing something. For example, choosing between using a CALS table or a simple table or choosing between using conkeyref, keyref, or conref to reuse small pieces of text. Why even have the <simpletable> element in the DITA standard at all, since a CALS table without cells spanning is simple enough? The LightWeight DITA Project is an alternative to DITA and it tries to simplify the standard and eliminate such problems:
  • DITA elements that have conrefs or conkeyrefs need to also have the required content specified in them. So I cannot simply do this:
    <table conref="path/to/target.dita#topicID/elementID"/>
    Instead, I need to do this:
    <table conref="path/to/target.dita#topicID/elementID">
      <tgroup cols="1">
    and have all the required table elements and tgroup elements (plus required attributes) filled out even if the expanded conref will replace the entire original element.
  • You cannot reference directly to a subtopic element using a key. If the standard would allow a DITA Map to reference directly to a subtopic element like this:
    <keydef href="topics/reusableComponents.dita#topicID/tableID" keys="reused_table"/>
    you could reuse the table without needing to specify the ID to the reused element on each conkeyref:
    <table conkeyref="reused_table"/>
  • Some DITA elements (eg: <li>, <entry>, <section>) have a very relaxed content model in the specification allowing both text and block elements, in any order. So when using visual editing tools, this leads technical writers to create DITA content that looks like this:
            <p>Here are some of the preview</p>
    as the visual editing tool cannot, by default, impose an editing constraint if the standard does not. Usually, for such cases additional Schematron checks can be handy.
  • The DITA content is not automatically profiled based on the new DITA 1.3 deliveryTarget attribute. So setting deliveryTarget="pdf" on a DITA element will not automatically filter it out of the HTML based outputs, the attribute is treated just like another profiling attribute, and it can be filtered out from the DITAVAL file.

This concludes my complaint list. Anything else you encountered in the DITA standard that bothers you?

Friday, June 30, 2017

DITA Linking Strategies

Share to Facebook Share to Twitter Email This Share on Google Plus Share on Tumblr

This small tutorial is based on the "DITA Linking Strategies" presentations I made for the DITA Europe 2016 and DITA North America 2017 conferences. It's a general overview about DITA linking possibilities and best practices. Also, it's meant as a continuation of the DITA Reuse Strategies blog post.

According to Wikipedia:

"A link, is a reference to data that the reader can directly follow either by clicking, tapping, or hovering."

Basically, we should regard linking as yet another form of content reuse, except that instead of presenting the content in place, it re-directs the end user to some other resource.

I'll start with describing linking at DITA Map level.

Map-Level Linking

A DITA Map uses topic references to assemble the content of a publication.
 <topicref href="installation.dita">
  <topicref href="server_installation.dita"/>
  <topicref href="client_side_installation.dita"/>

Depending on the output format, the topic reference may be a link in the table of contents for the XHTML-based outputs or it may be interpreted as a content reference for the PDF-based output that generates a single monolith document. So the role of the topicref is dual, it may sometimes be regarded as a link to a topic and sometimes as a content reference.


DITA topic modules should be kept as small as possible, but sometimes the end user may need to read more than one topic to achieve a single task. So, when publishing to HTML-based outputs, you will end up asking yourself this question:

Should I prefer larger HTML files or more links in the TOC?

And you should always consider these two ideas:
  • Links are disruptive. Ideally, users would not need to jump around in content to read the entire story they are searching for.

  • Small topics that are usually read consecutively by the end user can probably get merged together.
For example, if the installation of your product requires installing both a server-side and a client-side component, by using DITA chunking you can choose to have separate DITA topic modules for each of the installation procedures but merge the topics together in the web-based outputs:
 <title>User Guide</title>
 <topicref href="installation.dita" chunk="to-content">
  <topicref href="server_installation.dita" toc="no"/>
  <topicref href="client_side_installation.dita" toc="no"/>

You can read more about chunking in the DITA 1.3 specification. The DITA Style Guide also has a good overview about why it is preferable to write small topics and then merge them together using the chunking mechanism.

Topic-Level Linking

Links that appear inside topics can be divided into various categories and I'll discuss each of these categories separately.

In-Content Links

In-content links are links added manually in the topic content:
<li>See: <xref href="http://www.../" format="html" scope="external"/></li>

You should keep in mind that this kind of link is disruptive to the reading experience because when end users encounter them, they need to decide weather to read further on or to follow the link. On the other hand, this may sometimes be a good thing. For example, one of the installation steps may require the end user to download a certain library from an external website before continuing.

You can read more about links in general in the DITA 1.3 specification. The DITA Style Guide, written by Tony Self, also discourages the use of in-content links.

Related Links

Related links are placed at the end of the DITA topic and they allow the end user to explore additional resources after the current topic has been read.
    <link href="" format="html" scope="external"/>

To minimize disruption when reading the content in general, the preferred place where to place links is at the end of the generated HTML page.

You can read more about related links in the DITA 1.3 specification.

Defining Related Links using Relationship Tables

Related links do not need to be manually added at the end of each topic. You can define relationship tables in the DITA Map:
    <topicref href="client_side_installation.dita"/>
    <topicref href="server_installation.dita"/>

These tables can define associations between two or more topics, associations that automatically contribute to the related links creation in the generated HTML output.

Here are some benefits of using relationship tables:
  • A topic should have as few links as possible defined directly within. This makes it easier to reuse the topic in various contexts and keeps it as separate as possible for other parts of the DITA project, decreasing the possibility of broken links.

  • By default, links defined in relationship tables are bi-directional, allowing users to land on any of the topics when searching for solutions and find their way to the related ones.

  • Using a relationship table separates the task of writing topics from the task of finding relationships between topics.

You can read more about relationship tables in the DITA 1.3 specification. The DITA Style Guide also recommends using relationship tables.

Indirect Links (Key References)

All the link samples we've look at so far have been direct links, links that point to the target using the @href attribute. Indirect links require two steps:
  1. Define a key in the DITA Map for the target.
    <keydef keys="client_installation" href="client_side_installation.dita"/>
  2. Use the defined key to reference the target resources.
    <xref keyref="client_installation"/>
Here are some of the benefits of indirect linking:
  • Offers the ability to reuse link target text and meta data. If you want to have custom text for a certain link, you can define it directly in the DITA Map:
    <keydef keys="dita_ot_website" href="" format="html"
       <linktext>DITA Open Toolkit Web Site</linktext>
    and then add key references in all other places:
    <xref keyref="dita_ot_website"/>
  • Easier conditional linking (including links to topics that sometimes may be missing). If you want your topic to link either to one target or to another depending on the filtering/profiling conditions, instead of adding profiling directly on the link, you can add the profiling conditions directly in the DITA Map:
     <topicref keys="slicing" href="slicing_vegetables_for_experts.dita" audience="expert"/>
     <topicref keys="slicing" href="slicing_vegetables_for_novices.dita" audience="novice"/>
     <keydef keys="slicing" audience="noLink"><topicmeta><keywords>
    and then link to the key from each topic:
    <xref keyref="slicing"/>
  • Easier link management. A good overview about all the outbound links in your project helps you maintain and control lists of allowed external web sites. With indirect references, you can define all references to external resources in a separate DITA Map. An example of a DITA project using indirect links to achieve separation of links by purpose can be found here:

  • Makes it easier to move/rename topics. When you move or rename a topic referenced via indirect links, only the link defined in the DITA Map will break, making it easier to fix broken links.

There is an overview about indirect addressing on the DITA XML Org website. The DITA 1.3 specification also has a chapter about indirect links.

Auto-Generated Links

Until now, I've talked about manually added links, either in the topic or in relationship tables. Using the DITA @collection-type attribute, you can define relationships between parent and child topic references in the DITA Map, relationships that result in automatic links added between them:
 <topicref href="installation.dita" collection-type="sequence">
  <topicref href="server_installation.dita"/>
  <topicref href="client_side_installation.dita"/>
There are 3 useful types of @collection-type values:
  • Unordered - Links are generated from parent to children, and from children to parent.

  • Family - Links are generated from parent to children, from children to parent, and from sibling to sibling.

  • Sequence - Links are generated from parent to children, from children to parent, and from child to previous sibling (if applicable) and next sibling (if applicable).

You can read more about auto-generated links in the DITA Style Guide.

Conditional Links in Distinct Publications

You may publish documentation for multiple products from the same DITA content. Also, you may want to have links point to various targets depending on the product for which you want to publish the documentation. Or, you may want to suppress links completely in certain publications.

When using direct linking, you will need to profile each link depending on the publication:
Find our more about slicing vegetables: <xref href="slicing_vegetables_for_experts.dita" audience="expert"/>
<xref href="slicing_vegetables_for_novices.dita" audience="novice"/>.
With indirect links, you can define the profiling attributes as DITA Map level:
 <topicref keys="slicing" href="slicing_vegetables_for_experts.dita" audience="expert"/>
 <topicref keys="slicing" href="slicing_vegetables_for_novices.dita" audience="novice"/>
and thus, simplify the reference made in the topic content:
Find our more about slicing vegetables: <xref keyref="slicing/>.

Conditional Links in the Same Publication

Using DITA 1.3 key scopes, you can reuse a topic multiple times in a DITA Map and have each referenced topic contain links to various target topics. For example, if my preparing_vegetables.dita topic has a link:
<link keyref="slicing"/>
you can define various key scopes in the DITA Map that bind the "slicing" key to various targets:
 <topichead navtitle="Cooking for Experts" keyscope="expert">
  <topicref href="preparing_vegetables.dita" keys="preparing"/>
  <topicref href="slicing_vegetables_for_experts.dita" keys="slicing"/>
 <topichead navtitle="Cooking for Novices" keyscope="novice">
  <topicref href="preparing_vegetables.dita" keys="preparing"/>
  <topicref href="slicing_vegetables_for_novices.dita" keys="slicing"/>

This previous blog post contains more details about key scopes.

Link Text

When linking to an external resource or to a DITA topic or element, the publishing engine will attempt to deduce the link text from the target context. For example, the link to a DITA topic or element that contains a <title> will use that title as the link text. The link to an external resource (for example to will, by default, use the HTTP location as the link text. You can also customize each link text individually. So, ask yourself this question:

Should I leave the link text to be automatically computed or should I set a more friendly text?

For internal links to elements that have a title, in general it is more flexible to not set a custom text and let the publishing engine decide one for you. For external links, you should usually specify your custom link text.

Should I Link or Should I Reuse?

Suppose you want to bring a certain paragraph, note, or section to the end user's attention. If that particular target element is not very large, you should always reuse it (using a content reference) instead of linking to it.


As with all large projects, managing links in a growing DITA project can be problematic, so you need to become organized. As an overview of what we've discussed so far, I suggest the following best practices:
  • Linking is a form of reuse so:

    • Reuse small pieces of content instead of linking to them
    • Avoid too much linking (linking is disruptive)
  • Use indirect links. It will allow you to reuse link text and make profiling/filtering easier while giving you a better overview of the outbound links for your project.

If you want to experiment with the various linking strategies I discussed above, you can find some samples here: