Create walk-through and acceptance scripts with single-sourced DITA

Benefit from document reuse throughout your development cycle

Paired with a validating XML editor, Darwin Information Typing Architecture (DITA) provides a useful tool for developing topic-based user documentation that describes how to use your application. With a bit of forethought and planning, you can repurpose these same topics into documents that provide value much earlier in the development process, such as walk-through scripts for use in client demos or acceptance scripts for a manual quality assurance effort.


Piers Michael Hollott, Senior Consultant, Sierra Systems

Piers has worked in the software industry for 15 years, and specializes in Java development, XML technologies, and functional programming. He has contributed to several open source projects and is currently a consultant with Sierra Systems.

02 November 2010

Also available in Chinese Japanese

As your software development project and development team grow, you might need to create reference documentation such as a user guide for internal or external use. Creating this sort of documentation becomes more cumbersome the longer you defer it. Developing a framework that supports creating multiple types of documentation from a single source can be advantageous for small and large projects alike; with forethought, you can also leverage this documentation to support your project's quality assurance (QA) and testing needs. This article shows how the DITA and XSLT 2.0 transformations can facilitate a single-sourcing strategy for both development and user documentation.

Frequently used acronyms

  • DBMS: Database management system
  • DTD: Document type definition
  • HTML: Hypertext Markup Language
  • OASIS: Organization for the Advancement of Structured Information Standards
  • PDF: Portable Document Format
  • RSS: Really Simple Syndication)
  • UI: User interface
  • XML: Extensible Markup Language
  • XSL: Extensible Stylesheet Language
  • XSLT: Extensible Stylesheet Language Transformation

The XSL transforms provided with this article (see Download) are an extension of an open source project I developed five years ago as an attempt to shorten both documentation and QA time. I wanted to reduce the task of collecting use cases and turning them into client acceptance tests, which were then reused as a training resource for new developers. In some respects, this project reflects a breakdown of business intelligence; I played the role of QA, technical writer, and development lead. Taken in another light, I see this work as an early indicator of agile strategies that I have found indispensable in subsequent projects—surfacing often by facilitating client walk-throughs, looser coupling with use cases, and getting just enough done to move forward.

As this project grew, I ended up with a large XML file persisted in an XML DBMS. It contains a description of the high-level application architecture of the software under development and was broken into modules, pages, page states, and controls on the page. Along with this file, I built a collection of XQuery and XSL transforms that could extract and publish a user guide, an acceptance test document, and an RSS feed containing a navigation path through the application based on changes made in the previous two-week period. The RSS feed drove the manual testing effort.

At the time, although I had heard of DITA, I had no practical experience with what was then a relatively new specification. So, I created my own schema, started to collect data, and developed my transforms. My reading about DITA no doubt influenced the approach I took as I:

  • Addressed modularity and reuse
  • Wrote a basic topic structure
  • Created collections of concepts and task lists

Start with DITA topics: concepts, tasks, and topic maps

The sample application this article describes is incredibly simple. It has a home page and a three-page wizard that you can use to enter the name and address of a person. This application does not actually exist—that is, it exists only in theory. It contains a single path (although I intend to expand the sample files to include multiple alternate flows in a future iteration).

The data used to create the user guide is separated into pages and cases, where each page represents a single HTML page and a case represents a simple use case, such as "Enter your name into the name field, and verify that it is capitalized properly." These topics are collected into a DITA topic map, which you can use to generate a PDF file containing a page-by-page user guide using the DITA Open Toolkit.

The DITA approach to topic-based writing focuses on three fundamental types of topic:

  • Concepts, which tend to be abstract
  • References, which tend to be more concrete
  • Tasks, which describe the steps taken to accomplish something

Listing 1 shows a sample concept; Listing 2 shows a sample task. Once you have a number of written topics, you can collect and organize them into a document using a topic map, which is similar to table of contents. You can use the same topics with multiple topic maps to produce multiple documents.

Each page in the sample application is represented with a DITA concept, tying together a description of the page’s purpose, a collection of the navigation controls on the page, and references to any use cases that are appropriate for this page. You can see in Listing 1 how the DITA concept describing a page contains a description of the UI elements on the page and references to a single use case task.

Listing 1. A DITA concept for an application page
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE concept PUBLIC "-//OASIS//DTD DITA Concept//EN"
<concept id="wiz2" xml:lang="en-us">
    <title>Wizard Page 2</title>
        <p>Name Details</p>
            <title>User Interface: Controls</title>
                <uicontrol id="wiz3">Continue</uicontrol>
                <uicontrol importance="optional" 
            <title>Use Cases</title>
            <xref href="../cases/case_004.dita" type="task"/>

The elements screen and uicontrol are typically used in DITA documents to describe UI components. They're used for this purpose in this article as well, but as you will see, these elements also calculate a navigation path through the sample application.

Use cases are represented with DITA tasks, which identify a discrete set of steps taken to produce a result. When I used this approach to document an actual application, I also added cases for known issues, tagged with a keyword regression, and excluded them from the user guide. When the topic map is repurposed for use as a testing document, these regression tests can be included, providing a context for manual testing.

Listing 2 shows a DITA task detailing the steps required to reproduce an action that can be carried out on a page. Notice how one of the steps—adding a middle name—is marked as optional.

Listing 2. A DITA task for an application use case
<?xml version="1.0" encoding="utf-8"?>
<task id="case_004" xml:lang="en-us">
    <title>Case 004</title>
        <context><p>context: case 004</p></context>
            <step><cmd>Enter First Name</cmd></step>
            <step><cmd>Enter Last Name</cmd></step>
            <step importance="optional"><cmd>Enter Middle Name</cmd></step>

The folder structure for the sample DITA project is very flat, with directories for cases and pages. Later, these directories will be accompanied by a directory for tests. In addition, a directory is maintained for the XSL transforms used to generate the test topics. DITA topic maps are kept in the root of the project.

The DITA topic map for this simple application, in Listing 3, is also simple. When you use the DITA Open Toolkit to generate a user guide, the results are straightforward and useful, and you can easily add information to the individual page files to add complexity and depth. You can see how the topic map is like a table of contents containing four sections.

Listing 3. A DITA topic map
<?xml version="1.0" encoding="utf-8"?>
<map title="Sample Application User Guide">
    <topicref href="pages/home.dita" type="concept" id="home"/>
    <topicref href="pages/wiz1.dita" type="concept"/>
    <topicref href="pages/wiz2.dita" type="concept"/>
    <topicref href="pages/wiz3.dita" type="concept"/>

Transform topics into a walk-through document

Because the DITA screen and uicontrol elements were used to describe the navigation controls (links, buttons, and menus) on a page, it is not a complicated piece of engineering to extract information from the individual DITA page files and use this information to create a new set of DITA tasks. These tasks describe how to navigate from one page to another—for instance, as in the navigation task nav_home_wiz1.dita, in Listing 4. You can see how the naming convention concatenates the identifiers for the two pages to represent navigation from one to the other; the information from the original page concept now represents a navigation task.

Listing 4. A navigation task
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE task PUBLIC "-//OASIS//DTD DITA Task//EN" "../dtd/task.dtd">
<task id="nav_home_wiz1.dita" xml:lang="en-us">
    <title>Navigate to Wizard Page 1</title>
                <cmd>On Home Page, click 
                    <uicontrol>Launch Wizard</uicontrol>
                <cmd>Verify that Wizard Page 1 loads</cmd>

The navigation tasks are kept in a new directory called tests alongside the pages and cases directories. In addition to these tasks, tests contains a new set of test concepts—one for each page—that simply identify that the page is being tested. You can expand these concepts, like the wizard page testing concept in Listing 5, to include more information about how to test the page—for instance, identifying which pages apply to which user roles, priority and severity of testing, and so on.

Listing 5. A testing concept
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE concept PUBLIC "-//OASIS//DTD DITA Concept//EN" "../dtd/concept.dtd">
<concept id="test_wiz1.dita" xml:lang="en-us">
    <title>Wizard Page 1</title>
        <p>This is the first wizard page: Name Details</p>

The information contained in each test concept document is drawn directly from a DITA concept in the pages directory. In fact, all the topics contained in the tests directory are generated directly from the topics in the other two directories and the user guide topic map (in Listing 3) using XSLT. Listing 6 shows a new walk-through topic map that is also generated from these same files. When you supply the walk-through topic map as a parameter to a build script in the DITA Open Toolkit, the toolkit uses the new tasks and concepts to generate a walk-through script that traverses the navigation graph for the sample application. The result is a path through the application that guides a structured walk-through of the application for either internal audit or client use.

For each page, the walk-through script also contains acceptance criteria drawn from the use cases, which you can use as a talking point during a client demo or manual testers can use during user or factory acceptance testing. And because you can regenerate the entire tests directory whenever the content in the other two directories is altered, you can regenerate this document and use it at any stage in your development cycle, whether you have a single page or a hundred pages.

Listing 6. The walk-through DITA topic map
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE map PUBLIC "-//OASIS//DTD DITA Map//EN" "../dtd/map.dtd">
<map title="Sample Application User Guide">
    <topicref href="tests/test_home.dita" type="concept">
        <topicref href="pages/../cases/case_001.dita" type="task"/>
        <topicref href="pages/../cases/case_002.dita" type="task"/>
    <topicref href="tests/test_wiz1.dita" type="concept">
        <topicref href="tests/nav_home_wiz1.dita" type="task"/>
            <topicref href="pages/../cases/case_003.dita" type="task"/>
    <topicref href="tests/test_wiz2.dita" type="concept">
        <topicref href="tests/nav_wiz1_wiz2.dita" type="task"/>
            <topicref href="pages/../cases/case_004.dita" type="task"/>
    <topicref href="tests/test_wiz3.dita" type="concept">
        <topicref href="tests/nav_wiz2_wiz3.dita" type="task"/>
        <topicref href="pages/../cases/case_005.dita" type="task"/>
        <topicref href="pages/../cases/case_006.dita" type="task"/>
    <topicref href="tests/test_home.dita" type="concept">
        <topicref href="tests/nav_wiz3_home.dita" type="task"/>

Streamline for an XSLT 2.0 rescue

When I first developed a schema to model the information used to create and repurpose these documents, I attempted to avoid an issue that I encountered on an earlier project. Previously, I had developed schemas that were too granular; now, conversely, my file was too monolithic, keeping all of my XML in a single file. This idea does have several advantages, of course, such as reducing file administration and versioning issues, while also reducing the complexity of the transforms necessary to generate new information. Although a monolithic approach is possible with DITA using the ditabase element (which basically serves as a container for DITA topics such as concept, task, and reference), a common best practice in the DITA community is to create one DITA topic for each file. A more granular approach such as this allows superior version control and facilitates reuse and repurposing, which is really the point of the current undertaking.

To make it as granular as possible, which is what I have done, is more efficient. Regarding the XSL transform itself, increased granularity raises two major issues: pulling information out of multiple files and then pushing information back into multiple files. To retrieve information from multiple files, I used the xsl:document() function, which is easy to use as long as you are dealing with a flat file structure. To generate multiple documents in the tests directory from these various DITA documents, I used the xsl:result-document element, which was introduced with XSLT 2.0. Listing 7 and Listing 8 demonstrate how you would use xsl:result-document in the XSL transform to create a new concept and a new task.

Listing 7. Using xsl:result-document to generate a DITA concept
<xsl:result-document href="..\{$doc-path-test}" 
    doctype-public="-//OASIS//DTD DITA Concept//EN">
    <concept id="{$doc-name-test}" xml:lang="en-us">
            <xsl:value-of select="title"/>
                <xsl:value-of select="conbody/p"/>

Note: Notice how in both Listing 7 and Listing 8 the doctype-system and doctype-public attributes available to xsl:output-encoding are also available for the xsl:result-document element. Without these, it is not possible to attach the appropriate DITA DTDs to the generated files; without these DTDs, you cannot use the generated files with the DITA Open Toolkit. Therefore, the use of these attributes is critical.

Also, whereas using DITA tasks to represent use cases makes reasonable sense, representing pages with DITA references rather than concepts also is sensible because they refer to real-world things such as HTML pages. I decided to use concepts to represent pages because I knew that I would generate the more abstract test concepts from them and that I wanted to maintain this alignment. In other words, this was an arbitrary choice.

In Listing 8, you can see how the XSLT to generate a navigation task document is a bit more complicated than that used to generate a concept.

Listing 8. Using xsl:result-document to generate a DITA task
<xsl:result-document href="..\{$doc-path-nav}" 
    doctype-public="-//OASIS//DTD DITA Task//EN">
    <task id="{$doc-name-nav}" xml:lang="en-us">
        <title>Navigate to <xsl:value-of select="title"/>
                    <cmd>On <xsl:value-of select="$source_title"/>,
                         click <xsl:copy-of select="$uicontrol"/>
                    <cmd>Verify that 
                        <xsl:value-of select="title"/> loads</cmd>

Again, notice the use of the doctype-system and doctype-public attributes to attach the appropriate OASIS DITA DTD to the topic that the XSL transform created. Refer to Listing 4 to see an example of the task created.

When the new documents are generated, they are referenced within the same XSL transform that generated them, as in Listing 9. You use these references to create the new walk-through topic map from the existing user guide topic map by recursively following the id attributes contained within the uicontrol elements in the source page concepts. Using XSLT 2.0, I was able to use a single transformation to create the topic map and all supporting files—an accomplishment that simply would not be possible (or at the very least would not be enjoyable) using XSLT 1.0.

Listing 9. Referencing the generated testing concept and task
<topicref href="{$doc-path-test}" type="concept">
    <topicref href="{$doc-path-nav}" type="task"/>
    <xsl:if test="@id != 'home' ">
        <xsl:apply-templates select="conbody" mode="cases"/>

Note: To see the full XSL transform, download the attached sample files.

Whenever you change the content used to generate these topics, you can regenerate new topics so the walk-through or acceptance documentation is timely and up to date. For instance, a build script might remove any existing generated files, run the user guide-to-walk-through transform, then use the DITA Open Toolkit build scripts to generate current copies of the user guide and acceptance or walk-through documents as PDF files.

Because the DITA screen and uicontrol elements describe navigation controls (see Listing 1), traversing a path through the application becomes a matter of simple recursion. I used the importance attribute (which is common to DITA elements) throughout to represent navigation controls that are optional, such as Cancel buttons, which can be ignored for the purpose of navigation. A similar strategy is used to prevent the dreaded stack overflow, which occurs when navigating away from a page returns flow to a page that was previously traversed. I also found the otherprops attribute to be useful for this purpose—again, because it is common and easily available to all DITA elements.

Looking forward

For a simple application, I have described a simple transform. I hope that this article demonstrates how to develop a strategy of document reuse along with some benefits of initiating documentation projects early so you can repurpose them both immediately and throughout the life cycle of your software project. Using a single source to generate multiple document projects that crosscut the various stages of the development cycle opens further opportunities to leverage this shared knowledge. This approach is important because if a documentation is used by multiple stakeholders in a software project, it is much more likely to be maintained and to gain value over time.

Applying a more flexible approach to documentation also has the advantage of crosscutting methodologies. If you are involved with a client, for example, who demands a high level of formality and ceremony but your development team practices an agile methodology, repurposing documentation might be exactly the approach you need to address the demands of both your client and your chosen methodology. If this is the case, DITA and XSLT 2.0 might be just the tools you need.


Source files for the DITA projectsample_code.zip44KB



Get products and technologies

  • DITA Open Toolkit: Download the open source toolkit for processing DITA.
  • IBM product evaluation versions: Download and get your hands on application development tools and middleware products from DB2®, Lotus®, Rational®, Tivoli®, and WebSphere®.



developerWorks: Sign in

Required fields are indicated with an asterisk (*).

Need an IBM ID?
Forgot your IBM ID?

Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.


All information submitted is secure.

Dig deeper into XML on developerWorks

ArticleTitle=Create walk-through and acceptance scripts with single-sourced DITA