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 and linking potential and it's in general well thought and comprehensive.

Over the years various of our Oxygen XML Editor clients or me personally have encountered various limitations/quirks in the DITA standard that I wanted to share 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 probably a good part of these issues could not be effectively fixed because the DITA standard has strived (and succeeded) to be backward compatible. So here we go:
  • When I create a DITA specialization in order 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, just sometimes you would 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 output either for one language or the other by filtering out 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 in order to remove entire table columns when publishing. So the alternative is to use a DITA simpletable 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 dynamic 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 too 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 have the <simpletable> at all in the DITA standard as long as a CALS table without any cells spanning is simple enough? The LightWeight DITA Project is an alternative to DITA which tries to simplify the standard and eliminate such problems:
  • DITA elements which 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"/>
    and 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 refer using a key directly to a subtopic element. If the standard would allow a DITA Map to refer 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 create DITA content looking 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 which 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:

Friday, June 16, 2017

Checking terminology when editing in Oxygen XML Editor

Share to Facebook Share to Twitter Email This Share on Google Plus Share on Tumblr
In this blog post I will offer a general overview about the current possibilities you have available to impose your own language checking rules when working with Oxygen XML Editor.

Built-in support

Oxygen comes bundled with the popular Hunspell spell checker and along with the regular bundled dictionaries for English, German, Spanish, and French, it allows you to install new dictionaries, either for other languages or custom dictionaries (for example, dictionaries for medical terms) that you can build separately:

Besides the spell checker, Oxygen also has support for Auto-correct and you can add your own Auto-correct pairs to Oxygen.

Commercial alternatives

Acrolinx is a very popular commercial tool for checking content for consistency and terminology. The plugins that Acrolinx developed for Oxygen standalone, Oxygen Eclipse plugin and Oxygen Web Author allow you to run the Acrolinx checker directly from inside the application.

HyperSTE is another popular commercial tool for checking content and terminology. They also have a plugin for Oxygen standalone.

Open-source alternatives

LanguageTools is an open-source proof­reading program for English, French, German, Polish, and more than 20 other languages . There is an open-source plugin for Oxygen available on GitHub.

The DITA Open Toolkit terminology checker plugin from Doctales contains Schematron rules to check that various words adhere to the terminology dictionaries that are custom built using DITA.

Building your own terminology checker

The fastest and simplest way to build a simple terminology checker is by using Schematron rules. The Doctales plugin is a good example for this.

At some point, as the terminology dictionary keeps growing, you may encounter delays and slow downs when editing the documents and validating it using the custom Schematron rules. So an alternative to this is by using our Author SDK to build your own Oxygen plugin, which can use our API to check the content and then add highlights. The LanguageTools open-source plugin may be a good starting example for this.

Monday, June 12, 2017

Batch converting HTML to XHTML

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

Suppose you have a bunch of possibly "not-wellformed" HTML documents already created and you want to process them using XSLT. For example, you may want to migrate the HTML documents to DITA using the predefined XHTML to DITA Topic transformation scenario available in Oxygen. So you need to create valid XML wellformed XHTML documents from the existing HTML documents and you need to do this in a batch processing automated fashion.

There are lots of open source projects that deliver processors that can convert HTML to its wellformed XHTML equivalent. For this blog post, we'll use HTML Tidy. Here are some steps to automate this process:
  1. Create a new folder on your hard drive (for example, I created one on my Desktop: C:\Users\radu_coravu\Desktop\tidy).
  2. Download the HTML Tidy executable specific for your platform ( and place it in the folder you created in step 1.
  3. In that same folder, create an ANT build file called build.xml with the following content:
    <project basedir="." name="TidyUpHTMLtoXHTML" default="main">
        <basename property="filename" file="${filePath}"/>
      <target name="main">
          <exec command="tidy.exe -o ${output.dir}/${filename} ${filePath}"/>
  4. In the Oxygen Project view, link the entire folder where the original HTML documents are located.
  5. Right-click the folder, choose Transform->Configure Transformation Scenarios... and create a new transformation scenario of the type: ANT Scenario. Modify the following properties in the transformation scenario:
    1. Change the scenario name to something relevant, like HTML to XHTML.
    2. Change the Working Directory to point to the folder where the ANT build file is located (in my case: C:\Users\radu_coravu\Desktop\tidy).
    3. Change the Build file to point to your custom build.xml (in my case: C:\Users\radu_coravu\Desktop\tidy\build.xml).
    4. In the Parameters tab, add a parameter called filePath with the value ${cf} and a parameter called output.dir with the value of the path to the output folder where the equivalent XHTML files will be stored (in my case, I set it to: C:\Users\radu_coravu\Desktop\testOutputXHTML).
  6. Apply the new transformation scenario on the entire folder that contains the HTML documents. When it finishes, in the output folder you will find the XHTML equivalents of the original HTML files (XHTML documents that can later be processed using XML technologies such as XSLT or XQuery).

Tuesday, April 25, 2017

DITA Inheritance Hierarchy

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

The DITA standard is based on this concept of inheritance which allows extending or restricting the vocabulary while allowing the XML content to still be regarded as valid DITA. Even in the DITA standard there are various element which are specializations of others (for example "b" is a specialization of ph"). The XSLT styesheets which are used for publishing match all DITA elements by the value of their @class attribute so knowing how elements may extend each other may be useful when customizing the DITA XSLTs.

A DITA inheritance hierarchy list for the base DITA specification is presented below. Would you consider it useful if a future version of Oxygen would have some kind of a tool to show such hierarchies even for custom DITA specializations?

  • topic/copyryear
  • topic/foreign
    • mathml-d/mathml
    • svg-d/svg-container
  • topic/author
  • topic/example
  • topic/unknown
  • topic/titlealts
  • topic/linktext
  • topic/category
  • topic/data
    • relmgmt-d/change-request-reference
    • relmgmt-d/change-person
    • relmgmt-d/change-request-id
    • relmgmt-d/change-request-system
    • relmgmt-d/change-completed
    • relmgmt-d/change-started
    • ut-d/sort-as
    • relmgmt-d/change-item
    • relmgmt-d/change-organization
    • relmgmt-d/change-summary
    • concept/data
      • glossentry/glossPartOfSpeech
      • glossentry/glossProperty
      • glossentry/glossStatus
    • relmgmt-d/change-revisionid
  • topic/longdescref
  • topic/audience
  • topic/abstract
    • concept/abstract
      • glossentry/glossdef
  • topic/related-links
  • topic/body
    • task/taskbody
    • concept/conbody
      • glossentry/glossBody
    • troubleshooting/troublebody
    • reference/refbody
  • topic/ph
    • hi-d/overline
    • hi-d/line-through
    • hi-d/sub
    • pr-d/sep
    • equation-d/equation-inline
    • pr-d/repsep
    • equation-d/equation-number
    • hi-d/tt
    • task/cmd
    • pr-d/synph
    • sw-d/userinput
    • ut-d/coords
    • pr-d/oper
    • hi-d/sup
    • pr-d/var
    • sw-d/msgph
    • pr-d/codeph
    • ui-d/uicontrol
    • hi-d/i
    • hi-d/u
    • sw-d/filepath
    • sw-d/systemoutput
    • pr-d/delim
    • hi-d/b
    • ui-d/menucascade
  • topic/object
  • topic/fig
    • ut-d/imagemap
    • pr-d/syntaxdiagram
    • equation-d/equation-figure
  • topic/featnum
  • topic/lines
  • topic/brand
  • topic/state
  • topic/source
  • topic/link
  • topic/vrm
  • topic/sli
  • topic/navtitle
  • topic/figgroup
    • pr-d/synblk
    • pr-d/fragment
    • ut-d/area
    • pr-d/groupcomp
    • pr-d/groupseq
    • pr-d/groupchoice
  • topic/note
    • hazard-d/hazardstatement
    • concept/note
      • glossentry/glossScopeNote
      • glossentry/glossUsage
  • topic/ol
    • task/substeps
    • task/steps
  • topic/stentry
    • task/choption
    • reference/propvalue
    • reference/propvaluehd
    • reference/propdeschd
    • reference/propdesc
    • reference/proptype
    • reference/proptypehd
    • task/choptionhd
    • task/chdesc
    • task/chdeschd
  • topic/dlentry
    • pr-d/plentry
  • topic/vrmlist
  • topic/entry
  • topic/fn
    • pr-d/synnote
  • topic/xref
    • mathml-d/mathmlref
    • svg-d/svgref
    • concept/xref
      • glossentry/glossAlternateFor
    • pr-d/synnoteref
    • pr-d/fragref
    • pr-d/coderef
  • topic/component
  • topic/series
  • topic/bodydiv
    • reference/refbodydiv
    • troubleshooting/troubleSolution
    • concept/conbodydiv
  • topic/data-about
  • topic/tgroup
  • topic/keywords
  • topic/boolean
  • topic/critdates
  • topic/strow
    • task/chrow
    • reference/property
  • topic/simpletable
    • reference/properties
    • task/choicetable
  • topic/linklist
  • topic/revised
  • topic/table
  • topic/dt
    • pr-d/pt
  • topic/image
    • hazard-d/hazardsymbol
    • concept/image
      • glossentry/glossSymbol
  • topic/ul
    • hazard-d/messagepanel
    • task/choices
    • task/steps-unordered
  • topic/p
    • concept/p
      • glossentry/glossSurfaceForm
    • troubleshooting/responsibleParty
  • topic/q
  • topic/linkinfo
  • topic/dd
    • pr-d/pd
  • topic/lq
  • topic/prodinfo
  • topic/dl
    • pr-d/parml
  • topic/prolog
  • topic/indextermref
  • topic/copyright
  • topic/div
    • equation-d/equation-block
  • topic/sthead
    • task/chhead
    • reference/prophead
  • topic/tbody
  • topic/searchtitle
  • topic/colspec
  • topic/created
  • topic/tm
  • topic/text
  • topic/cite
  • topic/li
    • hazard-d/howtoavoid
    • task/step
    • task/substep
    • hazard-d/consequence
    • hazard-d/typeofhazard
    • task/choice
    • task/stepsection
  • topic/permissions
  • topic/no-topic-nesting
  • topic/dlhead
  • topic/prodname
  • topic/index-base
    • indexing-d/index-sort-as
    • indexing-d/index-see
    • indexing-d/index-see-also
  • topic/indexterm
  • topic/copyrholder
  • topic/longquoteref
  • topic/required-cleanup
  • topic/ddhd
  • topic/sl
  • topic/draft-comment
  • topic/section
    • task/postreq
    • task/result
    • troubleshooting/remedy
    • task/tasktroubleshooting
    • concept/section
      • glossentry/glossAlt
    • task/context
    • troubleshooting/cause
    • task/steps-informal
    • reference/refsyn
    • task/prereq
    • troubleshooting/condition
  • topic/pre
    • sw-d/msgblock
    • pr-d/codeblock
    • ui-d/screen
  • topic/topic
    • troubleshooting/troubleshooting
    • concept/concept
      • glossgroup/glossgroup
      • glossentry/glossentry
    • reference/reference
    • task/task
  • topic/platform
  • topic/alt
  • topic/keyword
    • ui-d/shortcut
    • markup-d/markupname
      • xml-d/parameterentity
      • xml-d/xmlatt
      • xml-d/numcharref
      • xml-d/xmlpi
      • xml-d/textentity
      • xml-d/xmlnsname
      • xml-d/xmlelement
    • pr-d/parmname
    • pr-d/option
    • sw-d/cmdname
    • ui-d/wintitle
    • ut-d/shape
    • sw-d/varname
    • pr-d/apiname
    • pr-d/kwd
    • sw-d/msgnum
  • topic/thead
  • topic/publisher
  • topic/desc
  • topic/term
    • abbrev-d/abbreviated-form
  • topic/title
    • concept/title
      • glossentry/glossShortForm
      • glossentry/glossAbbreviation
      • glossentry/glossSynonym
      • glossentry/glossterm
      • glossentry/glossAcronym
  • topic/itemgroup
    • task/steptroubleshooting
    • task/tutorialinfo
    • task/info
    • task/stepxmp
    • task/stepresult
  • topic/row
  • topic/linkpool
  • topic/param
  • topic/shortdesc
  • topic/resourceid
  • topic/dthd
  • topic/metadata
    • relmgmt-d/change-historylist
  • topic/othermeta
  • topic/prognum
  • topic/sectiondiv

Wednesday, March 08, 2017

Useful DITA OT plugins

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

The DITA Open Toolkit is the most commonly used engine for publishing DITA content to various output formats. It has a plugin-based architecture and it comes bundled by default with plugins for publishing to XHTML-based and PDF formats. There are other useful open-source plugins which can be installed in the DITA Open Toolkit and provide various publishing or reporting capabilities. I will try to compile below a list with my favorite open source plugins, many of which are bundled by default with Oxygen XML Editor:

DITA to MS Word

This very useful plugin developed by Jarno Elovirta (the main DITA OT developer) can be used to publish DITA to MS Word (OOXML): The plugin is robust and can handle quite large DITA projects.

Convert MS Word to DITA

The DITA For Publishers project developed by Eliot Kimber contains a plugin which can convert MS Word (OOXML) documents to DITA topics: Useful advice and other ways to migrate from MS Word to DITA can be found here:


The DITA For Publishers project developed by Eliot Kimber contains a plugin which can convert DITA content to EPUB3: There are also plugins which can take the EPUB3 output and generate Kindle or Mobi formats.

Use Markdown content directly in DITA Maps

This plugin developed again by Jarno Elovirta can be used to publish hybrid DITA projects containing both DITA and Markdown topics to any output format:

Embed video and audio resources in DITA topics

This handy little plugin developed by Oxygen allows you to embed audio, video, or Youtube resources in DITA topics and properly display the embedded content in the XHTML-based outputs:

Publish RelaxNG-based DITA topics

RelaxNG is the default schema type in which the DITA vocabulary is described by the specification developers. But the DITA Open Toolkit does not allow publishing RNG-based DITA content by default. Installing this plugin developed by Oxygen will make this possible:

Present Oxygen track changes in the PDF output

This useful plugin developed by Oxygen allows you to preserve Oxygen change tracking highlights in the PDF output:

Publish DITA to PDF using CSS

The hard thing about the default PDF output is the customization which involves modifying XSLT scripts and having knowledge of both XSLT and XSL-FO. This plugin developed by Oxygen allows you to use CSS to customize the PDF obtained from DITA content: The plugin needs a commercial license of RenderX XEP or Antenna House in order to produce the PDF: But for Oxygen XML Editor 19 we are actively working on a PDF CSS engine which will allow the plugin to work from Oxygen without any additional licenses:

A list with all open-source DITA OT plugins developed and shared by Oxygen XML Editor can be found on GitHub: My DITA OT Day 2016 presentation covers most of these:

Tuesday, February 14, 2017

Customizing Oxygen XML Editor (Overview)

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

Let's assume you just bought Oxygen and want to customize it in order to better suit your team's workflow or to add support for your custom XML vocabulary. I will attempt to provide a set of use cases along with indications and useful links about what customization should be done in order to cover each use case:

Add support for editing a specific XML vocabulary

This kind of support usually should include:
  • New file templates.
  • Validate opened XML documents according to a custom schema.
  • Provide custom CSS to be used in the Author visual editing mode.
  • Provide custom toolbar, menu, and contextual menu actions to be used in the Author visual editing mode.
Such support is done using a document type/framework configuration:

Customize the existing support for a specific XML vocabulary

Oxygen comes with pre-configured framework configurations for the most commonly used XML standards such as DITA, Docbook, TEI, or XHTML. You may want to customize the existing configuration for one of these vocabularies and share the customization with others. Such customizations may include: All of these customizations can be done by extending the existing framework configuration and then sharing the extension:

Provide custom settings

You may want to provide all members of the team with a fixed set of options:

Modify the application appearance or behavior using plugins

Oxygen plugins can be used to:
  • Contribute custom views and toolbars for the entire application.
  • Filter out existing views or toolbar actions.
  • Contribute a fixed set of options/settings to the application.
  • Register various listeners and be notified when a document is opened, closed, saved, and so on.
  • Use the existing API to make changes to the opened documents.
A more detailed overview of Oxygen plugins can be found here:

The most popular plugin extension is the Workspace Access plugin extension: This extension is notified when the application starts and can contribute custom views, custom main menu items, custom main toolbar actions, or add listeners for various document-related changes.

There is also a JavaScript-based workspace access plugin extension that can use JavaScript to call our Java API:

A set of sample plugins built with the JavaScript-based extension can be found here:

Our Maven-based SDK can be used to develop both plugins and framework Java customizations:

Tuesday, February 07, 2017

Sharing Schematron Validation Rules

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

Custom Schematron rules are a great way to ensure consistency for the edited XML structure, especially when there is a large team working on the same set of documents. You can use Schematron for numerous use cases. For example, to make sure that certain elements are not used at all, to impose restrictions on the amount of text for an element, or to impose restrictions on certain elements based on various attribute values or text content set in other elements. Furthermore, you can define quick fixes for each Schematron rule to give the technical writer proposed solutions for the reported problem. In a previous blog post, I described how we use Schematron rules for our Oxygen User's Manual to impose restrictions when editing DITA content:

Once you define the Schematron rules, they can be shared with the other members of your team via a document type framework configuration:

In this post, I'm going to provide some precise steps to share a set of Schematron rules with a DITA framework extension.

Instead of making changes directly to the DITA framework configuration folder (located in OXYGEN_INSTALL_DIR\frameworks\dita) and distributing it, you can choose to extend the DITA framework and distribute the extension. This way, you will benefit from new functionality added to the base framework in newer versions of Oxygen and you can still use your customizations.

The following steps describe how you can extend a DITA framework that contains an additional Schematron rules file:

  1. Create a folder structure (for example, custom_frameworks/dita-extension) somewhere on your local disk, in a place where you have full write access.
  2. In that new folder structure, create another folder (custom_frameworks/dita-extension/rules) that will contain all of your custom Schematron files.
  3. Create a new ISO Schematron file (for example, additionalRules.sch) that contains the additional rules you want to impose. For example, the following Schematron rule reports an error if the @scale attribute is used on an image:
    <schema xmlns="" queryBinding="xslt2"
            <rule context="*[contains(@class, ' topic/image ')]">
                <assert test="not(@scale)">
                    Dynamically scaled images are not properly displayed, you
                    should scale the image with an image tool and keep it within
                    the recommended with and height limits.
  4. In the Document Type Association / Locations preferences page, add the path to your custom_frameworks folder in the Additional frameworks directories list. Click OK or Apply in the Preferences dialog to save your changes.
  5. In the Document Type Association preferences page, select the DITA document type configuration and use the Extend button to create an extension for it.
  6. Give the extension a custom name (for example, DITA - Custom), then change its Storage option to External, and then save it to a path such as: path/to/.../custom_frameworks/dita-extension/dita-extension.framework.
  7. Make whatever changes you desire to the extension, go to the Validation tab, edit the default DITA validation scenario, and add an extra validation stage to it (a stage that uses your custom Schematron schema). More details about validation scenarios can be found here:
  8. Click OK to close the dialog box and then either OK or Apply to save the preferences changes.

After you perform the steps above, in the dita-extension folder you will have a fully functioning framework extension that can be shared with others.

There are several methods for sharing the framework and you can read about them here:

After your team members install the framework, they can check the Document Type Association preferences page to make sure the framework is present in the list of Document Types and that it appears before the bundled DITA framework (meaning that it has higher priority).

You can use the framework extension mechanism to customize numerous aspects of the DITA functionality in Oxygen. For example, you can remove various elements from the content completion list: Or you can distribute custom new file templates:

Wednesday, January 18, 2017

Your First Oxygen Add-on

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

A framework configuration provides validation, content completion, and visual editing support for a certain XML vocabulary.

Existing framework configurations that come bundled with Oxygen can be extended and modified. For example, the DITA framework configuration that adds support for editing DITA documents can be modified to remove existing actions, add custom actions, or modify many other behaviors:

One way of distributing framework configurations is by using Oxygen's add-on support: An add-on configuration is usually composed of only two files:
  1. A ZIP file containing the zipped framework folder.
  2. An add-on XML configuration file that references the zipped framework folder and defines various properties of the add-on. A small example can be seen below:
    <xt:extensions xmlns:xt=""
        <xt:extension id="dita-extension">
            <xt:location href=""/>
            <xt:author>Radu Coravu</xt:author>
            <xt:name>DITA Extension which removes the bold action</xt:name>
            <xt:description xmlns="">
                This extension removes the bold action
    Everybody's welcomed to use this
    In the add-on descriptor file you usually need to specify the following :
    • The ID of the extension.
    • The version of the add-on.
    • The minimum supported Oxygen version.
    • Author name.
    • Name and description of add-on.
    • Licensing details.

Changing the add-on version in the XML file will trigger notifications to the end user to install the new add-on. Therefore, you can modify the framework customization in a common location and change the add-on version to signal all end-users who have installed the add-on that a new version is available. More details about packing an add-on can be found here:

If you want to test the small add-on I exemplified, you can find the sample add-on resources here:

Installing an add-on is straight-forward using the Install new add-ons dialog box from the Oxygen Help menu. You can add a reference to the add-on XML descriptor file that can reside either on the local hard drive or on a web server, and Oxygen will present all available add-ons:

The add-ons support can also be used to install Oxygen plugins. Some of the public hosted Oxygen plugins and frameworks are also available as add-ons:

In conclusion, if you want to share Oxygen customizations with others, you should try the add-on approach, it is a better approach to manually distributing frameworks and plugins.