Thursday, October 13, 2016

Replacing direct image references with key references in a DITA Project

Share to Facebook Share to Twitter Email This Share on Google Plus Share on Tumblr
Let's say that you have a large DITA project and all the image references in your topics are direct, using the @href attribute like this:
<image href="../../images/Iris_sanguinea.jpg" scale="50"/>
and for better scalability and reuse you want to convert these direct references to DITA 1.2 key references:
<image keyref="Iris_sanguinea.jpg" scale="50"/>

Doing something like this manually means making replacements in hundreds of places and in addition manually building a DITA Map which maps the image file name to the image location.

This blog post will try to describe some steps that you can take in order to automate this change in your project:
  1. The first big step is the generation of the DITA Map which maps each image file name (which will be used as a key) to the image location. So the generated DITA Map will look like this:
    <!DOCTYPE map PUBLIC "-//OASIS//DTD DITA Map//EN" "map.dtd">
    <map>
    ….…....
    <keydef href="Iris_sanguinea.jpg" keys="Iris_sanguinea.jpg"/>
    …...
    </map>
    We will assume that all images are placed in an images folder and we can create an ANT build file which lists all the images in a parameter and then calls an XSLT script to process the list of images further:
    <project basedir="." name="Create Image Keys Definition Map">
        <fileset id="dist.contents" dir="images/" includes="*"/>
        <property name="prop.dist.contents" refid="dist.contents"/>
        <xslt in="createKeyrefsMap.xsl" style="createKeyrefsMap.xsl" out="images/imageKeydefs.ditamap" destdir=".">
            <param name="filesList" expression="${prop.dist.contents}"/>
        </xslt>
    </project>
    The XSLT stylesheet createKeyrefsMap.xsl is responsible for creating the mapping DITA Map:
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:xs="http://www.w3.org/2001/XMLSchema"
        exclude-result-prefixes="xs"
        version="1.0">
        <xsl:param name="filesList"/>
        <xsl:output doctype-public="-//OASIS//DTD DITA Map//EN" doctype-system="map.dtd" indent="yes"/>
        <xsl:template match="/">
            <map>
                <xsl:call-template name="tokenizeString">
                    <xsl:with-param name="list" select="$filesList"/>
                </xsl:call-template>
            </map>
        </xsl:template>
        <xsl:template name="tokenizeString">
            <xsl:param name="list"/>
            <xsl:param name="delimiter" select="';'"/>
            <xsl:choose>
                <xsl:when test="contains($list, $delimiter)">
                    <keydef href="{substring-before($list,$delimiter)}" keys="{substring-before($list,$delimiter)}"/>
                    <xsl:call-template name="tokenizeString">
                        <xsl:with-param name="list" select="substring-after($list,$delimiter)"/>
                    </xsl:call-template>
                </xsl:when>
                <xsl:otherwise>
                    <keydef href="{$list}" keys="{$list}"/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:template>
    </xsl:stylesheet>

    So after this step you will have a new DITA Map with all image mappings, DITA Map which you can afterwards link in your main project's DITA Map.

  2. We still need to make changes to all DITA topics and replace all image hrefs with keyrefs. Oxygen has support for XML Refactoring actions and you can define custom XSLT scripts which can be applied to modify an entire set of topics. In the OXYGEN_INSTALL_DIR/refactoring folder you can add an XSLT script along with an XML description of the refactoring action. An XSLT script which would replace @href attributes on images with @keyref would look like this:
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        version="2.0"
        xmlns:xs="http://www.w3.org/2001/XMLSchema"
        xmlns:f="http://www.oxygenxml.com/ns/functions">
        <xsl:function name="f:getKeyref" as="xs:string">
            <xsl:param name="element" as="element()"/>
            <xsl:variable name="imageFile" select="tokenize(translate($element/@href, '\', '/'), '/')[last()]"/>
            <xsl:variable name="key" select="substring-before($imageFile, '.')"/>
            <xsl:value-of select="$key"/>
        </xsl:function>
        <xsl:template match="node() | @*">
            <xsl:copy>
                <xsl:apply-templates select="node() | @*"/>
            </xsl:copy>
        </xsl:template>
        <xsl:template match="image[@href and not(@keyref)]">
            <xsl:copy>
                <xsl:apply-templates select="@* except @href"/>
                <xsl:attribute name="keyref" select="f:getKeyref(.)"></xsl:attribute>
                <xsl:apply-templates select="node()"/>
            </xsl:copy>
        </xsl:template>
    </xsl:stylesheet> 
    In the DITA Maps Manager view you can right click and choose Refactoring->XML Refactoring, then use your custom refactor action to modify all resources.

A set of samples, including the build file, XSLT stylesheets and refactor action XML descriptor can be found here:https://www.oxygenxml.com/forum/files/batchImageHrefToKeyref.zip.

Thursday, October 06, 2016

Customizing the DITA Visual Editing Experience

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

The Author visual editing experience in Oxygen is CSS driven. Let's say I have a team of writers using Oxygen and they want to visually edit DITA dl elements in a table-like layout.

All the validation, editing and publishing support Oxygen has for a specific XML vocabulary is defined in a framework configuration.

Instead of copying an entire framework configuration folder (like DITA or Docbook), modify and distribute it you can choose to extend that framework and distribute the extension. In this way, you will benefit of new functionality added to the base framework by newer Oxygen versions and still use your customizations.

The steps below describe how an extension of the DITA framework which removes certain elements from the content completion list can be constructed and shared:
  1. Create somewhere on your disk, in a place where you have full write access a folder structure like: custom_frameworks/dita-extension.
  2. In that folder create a new CSS stylesheet called for example custom.css which will keep your custom CSS styles:
    dl{
        display:table !important;
    }
    dlentry{
        display:table-row !important;
    }
    dt, dd {
        display:table-cell !important;
        border: 1px solid black;
        padding: 2px;
    }
  3. In the Document Type Association / Locations preferences page add in your Additional frameworks directories list the path to your custom_frameworks folder. Then click Apply in the Preferences dialog.
  4. In the Document Type Association Preferences page select the DITA document type configuration and use the Extend button to create an extension for it.
  5. Give a custom name to the extension, for example DITA - Custom and then change its Storage to external, then save it to a path like: path/to/.../custom_frameworks/dita-extension/dita-extension.framework.
  6. Make changes to the framework configuration, in the Author tab click the CSS tab and add a reference to your custom CSS. Do not set a title for the CSS and also do not check the Alternate checkbox as you want your CSS to apply by default.
  7. Click OK to close the dialog and then either OK or Apply to save the preferences changes.

After you perform the steps above you will have in the dita-extension folder a fully functioning framework which can be shared with others: http://blog.oxygenxml.com/2015/08/document-type-extension-sharing.html.

To check that your framework extension works, you can create a new DITA topic and insert a dl element inside it. It should now be presented in a table-like layout.

In order to know which CSS styles to override for a specific DITA element, you can right click inside that element in the Author visual editing mode and use the Inspect Styles action to see all CSS styles defined for it by default. You can also define alternate CSS styles which are applied manually by the writer by using the Author toolbar Styles drop down menu.

Monday, October 03, 2016

DITA Linking Usage Survey

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

A couple of weeks ago I published a survey which was intended as an overview about DITA Linking habits. A big thank you to everyone who took it. The entire set of survey results, including the answers to open questions can be found here:

https://www.surveymonkey.com/results/SM-N8RJ6CJX/

Here are some comments I have about the results:
  • Most projects (including ours) seems to approach linking with a mixture between DITA 1.1 href's and DITA 1.2 keyrefs. In my opinion this is caused by a variety of factors among which the most important could be:
    • Technical writers who are not comfortable using indirection (keyrefs)
    • The project was started using href's and not all links have been converted to keyrefs
  • Almost everyvody using related links uses a relationship table to manage them. And that's good.
  • There are projects where related links, chunking and collection-type are not used at all. And I think this is not because the projects are not complex, but because the main output delivery format for those projects is PDF. In a DITA Reuse survey I opened last year there was a clear indication that PDF was still the most used output format: https://www.surveymonkey.com/results/SM-3WSR598S/.
Although harder to quantify I usually like answers to open questions best because you get a better idea about the difficulties of linking in DITA:
  • The large set of DITA linking possibilities make the standard harder to use. Too many options, harder for writers to understand and use keyrefs or relationship tables. There seems to be a need to have a best practice involving linking and DITA.
  • Various writers have various writing styles, leading to inconsistent projects.
  • Problems with the publishing part, even when the right DITA content is used for links (for example abbreviated-form) the publishing engine might have issues which break the link in the final output.
  • Problems with link management, with having a clear idea of outbound and inbound links and their target. Problems with broken links.
  • The tools used for editing DITA sometimes hide the complexity and even the type of link which gets created. Also the tools should help the writer easier find the target content to link to.