PDX DITA + WritetheDocs Meetup = Magic

A quick and enthusiastic report on last night’s PDX DITA holiday potluck with special guests from the WritetheDocs PDX Meetup Group. But first, a picture of happy documentarians.

meetup

We packed 30 people into our largest conference room for a delicious potluck (thanks Puppet team for the buffalo wings!) and a short presentation introducing DITA to prospective users. Leona Campbell and Melanie Jennings enthusiastically described the benefits and challenges of DITA as well as sharing experiences about what it’s like to get up and running with DITA when you’ve previously worked with different toolsets. Because we had a range of experiences at the table, from DITA consultants to working DITA writers to total newbies, there was a great ensuing discussion about why you’d want to use DITA rather than another tool. We also covered the need for different kinds of tooling depending on scale, the challenges of converting existing content versus writing topic-based content in DITA from scratch, and the always popular question of just how challenging it is to teach yourself DITA.

Another great outcome was the robust audience recommendations of resources, both print and online. We’ll be adding to the Resources section of this site soon, so stay tuned.

A big thank you to Mike Jang of WritetheDocs Meetup PDX for the opportunity to join forces, and to Melanie and Leona for a wonderful presentation. We’re looking forward to hearing more from our attendees, especially those who are starting up their DITA pilots soon.

 

 

Upcoming Holiday Potluck: WritetheDocs PDX Joins Us!

Our annual Holiday Potluck and final meeting of the year is upcoming on December 3rd. This year we’re featuring a special presentation aimed at new and prospective DITA users, which will also be a joint gathering with members of the WritetheDocs PDX Meetup Group. (We Jivers had a great time attending the WritetheDocs conference this past year, but DITA was not talked about in the presentations. That made us wonder why, and this event is one of the results.)

If you’ve been waiting to show up because you feel like you don’t know where to start learning about DITA, this would be a great time to dip your toes in the water. If you’re a grizzled veteran of DITA and/or PDX DITA, we want to see you too! We’d love to hear about your year in DITA and talk about what you’re doing next.

After last year’s potluck we feel confident in promising a delicious holiday feast. (Please bring a dish! We’re two blocks from Whole Foods and the carts, if you need inspiration.). Then Jive’s Melanie Jennings and Leona Campbell will present a brief introduction to writing in DITA XML, followed by Q&A and general conversation. As usual, we’ll provide beer, questionable witticisms, and stunning views of the Portland skyline.

Looking forward to seeing you!

 

Integrating the Oxygen WebHelp Plugin into the DITA Open Toolkit

I led a project earlier this year to convert my organization’s legacy Eclipse Help Center builds to HTML5 builds using Oxygen’s new WebHelp plugin for the DITA Open Toolkit. By changing the build output, we achieved the following:

  • Completely eliminated the costly Eclipse server maintenance
  • Improved our analytics results and potentially our SEO
  • Brought our output into HTML5 compliance

Unfortunately, actually implementing the plugin wasn’t just a matter of plopping the plugin into the Plugins directory. I had to upgrade the toolkit, rework scripts, and restructure directories to create a less-confusing, easily upgradeable build. Read on to understand my choices and learn from my experience.

Don’t look here to find a step-by-step procedure for implementing the Oxygen WebHelp plugin. Instead, read this blog post if you want help preparing for this process.

Upgraded the Toolkit

First, I upgraded our toolkit, which I was happy to do because it’s good practice, as well as nice to take advantage of the latest that DITA has to offer. Unfortunately, I couldn’t upgrade it too far, because the plugin only supports DITA-OT 1.7.5, which is still better than the 1.5.4 version we’d been using.

This time, I customized using the Customization directory only. My first experience with DITA was a highly customized DITA OT 4.2.1 that still makes me twitch when I look at it. It worked fine and it had some decent customizations, but upgrading a hacked-up toolkit is about as simple as string theory.

Reworked the Scripts

I reworked the .sh script and our ant scripts. The WebHelp plugin includes a dita.sh file that you need to edit in order to set environmental variables for the build. This replaces the toolkit’s OOB startcmd.sh and was actually a little tricky to figure out because I was retrofitting to an existing build layout.

The instructions from Oxygen tell you how to use the dita.sh, but don’t mention anything about ant builds, which is how we build here (via Jenkins). Oxygen’s support team was also less familiar with this approach. The reason I didn’t want to use only the dita.sh was that I didn’t want to have every writer set TRANSTYPE or DITAVAL_FILE or DITA_DIR  as environment variables every time she ran it from the command line.

For example, here’s what it would look like if the writer had to set all of the variables from the command line each time she ran a build:

"/usr/bin/java" -Xmx512m -classpath "docs/DITA-OT1.7.5LBC/tools/ant/lib/ant-launcher.jar" "-Dant.home=docs/DITA-OT1.7.5/tools/ant" org.apache.tools.ant.launch.Launcher -lib "docs/DITA-OT1.7.5LBC/" -lib "docs/DITA-OT1.7.5LBC/lib" -lib "docs/DITA-OT1.7.5/lib/saxonb9-1-0-8j/saxon9.jar" -lib "docs/DITA-OT1.7.5LBC/lib/saxonb9-1-0-8j/saxon9-dom.jar" -lib "docs/DITA-OT1.7.5/plugins/com.oxygenxml.webhelp/lib/license.jar" -lib "docs/DITA-OT1.7.5LBC/plugins/com.oxygenxml.webhelp/lib/log4j.jar" -lib "docs/DITA-OT1.7.5/plugins/com.oxygenxml.webhelp/lib/resolver.jar" -lib "docs/DITA-OT1.7.5plugins/com.oxygenxml.webhelp/lib/ant-contrib-1.0b3.jar" -lib "docs/DITA-OT1.7.5LBC/plugins/com.oxygenxml.webhelp/lib/lucene-analyzers-common-4.0.0.jar" -lib "docs/DITA-OT1.7.5/plugins/com.oxygenxml.webhelp/lib/lucene-core-4.0.0.jar" -lib "docs/DITA-OT1.7.5/plugins/com.oxygenxml.webhelp/lib/xhtml-indexer.jar" -f "docs/DITA-OT1.7.5/build.xml" "-Dtranstype=webhelp" "-Dbasedir=docs/sbs/7_0/trunk/src/dita/" "-Doutput.dir=docs/sbs/7_0/trunk/src/dita/out/webhelp" "-Ddita.temp.dir=docs/sbs/7_0/trunk/src/dita/temp/webhelp" "-Dargs.filter=docs/filters/on_prem_sys_admin_7_0.ditaval" "-Ddita.input.valfile=docs/filters/on_prem_sys_admin_7_0.ditaval" "-Dargs.hide.parent.link=no" "-Ddita.dir=docs/DITA-OT1.7.5" "-Dargs.xhtml.classattr=yes" "-Dargs.input=docs

Instead, I was able to revise the script so the build command now looks like this:

ant -Dargs.filter=docs/filters/on_prem_sys_admin_7_0.ditaval

My Goals for Reworking the Scripts

  • Simplify the build script so more than one user can build from their own environment
  • Automate the build
  • Produce PDFs along with HTML5 output
  • Make it possible to build using numerous maps, filters, and help sets

My Solutions for the Scripts

To reach these goals, I set the variables at build time using a series of build files that are triggered in one simple call on the command line that passes only the DITAVAL_FILE filter. Any writer, or build automation tool, can now use this command because the build scripts are no longer dependent on absolute paths to the DITA-OT or to an SVN repo.

On the command line or in Jenkins, any writer can run the new command in any help set directory, and the local build files reach out to a shared build file for all help sets. I put all of the targets in that one shared file, single-sourcing it like a good writer would.

I also wanted to preserve a previously-used script in our new build. It starts with a simple ant target that calls some .jars for creating PDFs. This target and its supporting .jars comb the main ditamap for submaps and create PDFs for each submap. This Chapter PDF output has been popular with our users, so I made sure we kept it.

Restructured the Directories

Because I was rewriting build files and creating new Jenkins scripts anyway, I figured it was a good time to flatten our directory structure a bit. I removed some unused directories, including some old build cruft and unnecessary branches (all highlighted in red).

Our former structure with extra layers:

  • productA/feature/ (used for eclipse output).
  • productA/version1/trunk/src/dita/
  • productA/version1/trunk/src/build/
  • productA/version1/trunk/output/
  • productA/version1/trunk/src/temp/

Here’s our new simpler way:

  • productA/version1/dita/
  • productA/version1/build/
  • productA/version1/output/
  • productA/version1/temp/

A next step is to research best practices for directory structures and DITA to further simplify our structure, but I’m happy to work in this slightly less cluttered place.

Customized WebHelp CSS and JavaScript

Knowing the hell of a customized toolkit made me extra concerned with customizing the Webhelp plugin. Although the plugin offers a lot, it does not provide a Customization directory. In order to change the look and feel of our HTML5 output, we had to edit the CSS and some JavaScript directly. This means that when/if we upgrade, it will take some work to transfer the changes to the new plugin. I already saw a huge reorg of files and directories between the pre-release and January versions of the same release.

Out of the box, Oxygen WebHelp plugin output looks pretty good:

Oxygen OOB Output

But I wanted to change our help to match our corporate style:
Jive Help Screen

Things to Ponder

  • Customizing the plugin might cause future headaches, but who wants OOTB?
  • Speaking of customizations: If you want to change the banner/header, brace yourself!
  • You will become an expert if you customize this plugin.
  • Upgrading even a non-customized toolkit is not always simple.
  • Oxygen Support is in Romania – an entire workday of waiting for responses is frustrating. But they are helpful and thorough, so ask them lots of questions.
  • Read the Oxygen Support forums (http://www.oxygenxml.com/forum/). There are some nuggets out there.
  • Hold out for the most stable version of the plugin, no matter how excited you are about it.
  • The Search and CSS are way better than in any other product we evaluated, but still clunky.
  • My last gripe about customizing this plugin is the utter lack of documentation. The paragraph on customizing the CSS cracked me up because they make it sound like you can use any ol’ CSS file, but you still need to point to the html elements that the plugin uses, such as 5 nested UL elements!

Was It Worth It?

Hell, yeah! I’m known for jumping head first into complicated projects, and this was no exception. (Someday, I’ll blog about improving PDF output using XSLT.) But, should YOU use this plugin? The answer is yes if you:

  • Want HTML5 output for an okay price.
  • Like the out-of-the-box look, or you want to learn (or already know) JavaScript and CSS.
  • Are comfortable using Support forums or Technical Support for help.

Have any of you had to implement the Oxygen WebHelp plugin? If yes, I’d love to hear your challenges and how you overcame them.

Getting Started with Filtering

In my last post about filtering, I tried to explain the theory of filtering, so you’d understand which kinds of problems filtering might solve. In this post, I’ll attempt to show how to get started on an actual project. This post is intended for folks who are just getting started with filtering.

Overall Process for a Filtering Project

Generally speaking, I find my process to be something like this:

  1. Create a matrix of the product’s variations and the associated publications so that I have a reference to consult for my sanity. Basically, I’m trying to sketch out which topics I’ll include and how to filter them in or out (in other words, show them or not show them in the final publication). This might be organized by features, audience, revision number, platform, or a combo of any of these.
  2. Use the matrix to define the values I’m going to need in my filter files. A “value” is the definition behind the features, audience, platform, etc. For example, the values might be “beginner,” “intermediate,” or “advanced,” or “Mac,” “Windows,” or “Linux”. Defining the values is basically figuring out who the audience is and the content they’ll need in the publication.
  3. Create the actual filter files (based on the values in the matrix) so that the computer knows how to show or not show tagged topics and inline text appropriately at build/publish time.
  4. Tag the content in the source files for the different features.
  5. Create the final publications (.doc, html, pdf, etc.) using each filter.

Create a Matrix

In my last post, I used the robot product as an example. The robot came in different models, so the matrix I created for that was based on features. But I find that when I change the example, that sometimes produces a different “aha” moment for readers. So this time around, I’m going to use a cookbook example that’s based on audience values (beginner and advanced).

I need to create a cookbook for two culinary school courses: Beginning Baking and Advanced Baking. I’ve determined the chapters I’m going to need and which ones I’ll be able to share between the two different cookbooks. Here’s how it looks:
Matrix

Define the Values

So in this case, we’re going to need two audience values:

  • Beginner
  • Advanced

Create the Filters

A filter is the actual file in which the values are defined. This may vary depending on which tool you’re using (Frame, Word, DITA, whatever), but the approach is generally the same between tools. As I mentioned in my last post, filtering is largely a mind-shift and less about which tool you’re using to accomplish the goal.

In my shop, we use DITA, so I would create a ditaval file for each of the cookbooks. (The filter files are called “ditavals” because they have a .ditaval filename extension).

  • Beginner
    beginning_ditaval
  • Advanced
    advanced_ditaval

Include/Exclude

Note that each of the ditavals includes/excludes the different audience values, like so:

  • Beginner — includes beginner, but excludes advanced.
  • Advanced — includes advanced, but excludes beginner.

The include/exclude action tells the computer which content to include and which to exclude when you publish your guide. So, for example, when you create the Beginner Guide, you want to see the following chapters:

  • Introduction
  • Cookies
  • Cakes and Pies
  • Basic Breads
  • Conclusion

You do not want to see:

  • Advanced Breads
  • French Pastry
  • Croissants

And when you create the Advanced Guide, you want to see:

  • Introduction
  • Cakes and Pies
  • Basic Breads
  • Advanced Breads
  • French Pastry
  • Croissants
  • Conclusion

You do not want to see:

  • Cookies

Tag at the Topic or Chapter Level

So, to accomplish this, you would “tag” the chapters so the computer knows what to show and what not to show at build/publish time. Again, in my shop, we use DITA, so my parent Cookbook file (called a “ditamap”) would look like this:

Cookbook_map

Breaking that Down

Introduction, Cakes and Pies, Basic Breads, and Conclusion are not tagged. That is because you want these to show (include) in both guides.

Here’s how the guides will look based on the include/exclude information in their associated filter file (the .ditaval):

  • Beginning Guide
    Will include Introduction, Cookies, Cakes and Pies, Basic Breads, Conclusion
    Will exclude Advanced Breads, French Pastry, Croissants
  • Advanced Guide
    Will include Introduction, Cakes and Pies, Basic Breads, Advanced Breads, French Pastry, Croissants, Conclusion
    Will exclude Cookies

If you don’t fully grasp this right now, try not to freak out. You’ll test it! You WILL get this to work. It just takes some time for your mind to adapt to this way of thinking.

Tag at the Inline Level

In addition to the topic-level tagging that you’ve done, you may have some text that you need to tag inline (e.g., specifying “audience=(value)” to specific elements). For example, in your Introduction chapter, you could do something like the following (apologies for crappy image; click it for better readability):

Inline_tagging_example_XML

For the xml-phobic, here’s a different view of that same content with some nice red arrows to explain what’s going on (again, click the image for better readability):

Inline_tagging_example_WYSIWYG

Refer back to the “Breaking it Down” section above to understand how this tagged content will show or not show in your different cookbook versions.

QA the Tagging

Here are a few ideas for QAing your tagging:

  • Your tool may have a handy way to validate your tagging. In other words, if you have tagged something incorrectly, your tool may have a way to let you know that and show you exactly where you messed up. In my shop, we use Oxygen, which has a great validator.
  • You can also design in your own quick QA checks. For example, one thing I’ve done in the past is to create a topic that lists the PDF guides. Here’s an example where the table rows are tagged for either “sys_admin” or “end_user” audience value. In the final publication, I can quickly glance at this topic and see if the correct row is showing (in this case, my ditaval filters are such that only the end user row or only the system administrator row should be showing). Here’s how the XML looks:
    Documentation PDFs file in XML

And again for the xml-phobic, here is the same file in the WYSIWYG-ish view. The green indicates content that is tagged:
Documentation PDFs file in WYSIWYG

  • Compare the TOC of the final output against the filter. Is anything showing that shouldn’t be, or vice versa?
  • Look at your build output for any error messages. We’ll explore filtering challenges in another post, but for now, here’s a quick example of a filtering-related error message:
    [FATAL] Failed to parse the input file ‘AdministeringIdeation.ditamap’ because all of its content has been filtered out. Please check the input file ‘AdministeringIdeation.ditamap’ and the ditaval file, and ensure that the input is valid.

Create the Cookbooks

Now that you have tagged everything and you’re ready to create the guides, you’ll push the magic button in whatever tool you’re using (for example, running the build on the command line; running the build in Oxygen; running the build via your CMS, or whatever). In Oxygen, I would choose my filter (e.g., beginning_baking.ditaval), my desired outputs (HTML, PDF, .doc, whatever), and then run the build. I would expect the result to be the Beginning Guide.

Start Small! But Start!

I tried to pick an example that was complicated enough to describe the power of filtering, but still accessible enough that it wasn’t completely overwhelming. My advice would be to pick a small project and practice on it until you get the hang of filtering.

If you have any questions, feel free to ask in the comments. Thanks for reading!

July 23rd Meeting: Keyrefs with Roger Hadley

At our upcoming meeting on July 23rd, Roger Hadley of Grass Valley Software will explain keyrefs in DITA 1.2. You’ll learn what they are, how to use them (with real-world examples), and a few publishing pitfalls to avoid. All DITA experience levels welcome!

As usual, we’ll also do a little meet-and-greet, and enjoy a light meal together. We hope to see you.

Details: Wednesday, July 23, 2014, 6:30 – 8:00 p.m.

Jive Software, 915 SW Stark, Portland

Some Resources for Getting Started with DITA

I’ll be giving a five-minute lightning talk about DITA tomorrow at the Write the Docs meetup at Puppet Labs. Here are some resources for anyone considering using DITA:

Please post your own resources in the comments here so we can all benefit. Looking forward to the meetup tomorrow!

Upcoming Workshop on DITA Authoring

We’re excited to announce that PDX DITA member, information architect, content strategist, Portland State instructor, and general bon vivant Toni Mantych will be teaching a two-day workshop called DITA for Authors on May 9 and 10th, 2014. The workshop is focused on authoring skills, and is aimed at people who already understand the importance of DITA and its value proposition, but don’t yet have extensive hands-on experience in the authoring medium. It will cover basic authoring knowledge like topic types and element use, but also will get into conditional filtering, keyrefs and conrefs and how to get the most value out of your content. Sounds extremely useful!

Full details are here: Dita for Authors

 

 

Understanding Filtering

It can be difficult to understand the power of filtering if you’ve never done it before. I’ll attempt here to explain filtering for beginners with plans to write another post about how to actually get started with filtering.

Problem

Many times when you’re writing and publishing large amounts of content as a technical, sales, or marketing writer, you need the same snippet or large section of content in several different publications. For example, you use the same Terms & Conditions or Executive Statement in all of your publications (your company website, your brochures, your online help center, and so on).

Solution

Rather than writing content over and over again, or keeping it somewhere on your network in a bunch of slightly different versions, filtering allows you to easily reuse content in many different contexts (your company website, your brochures, your online help center). Write it once, use it often. How we do this is called “filtering”. You might also hear it called “single-sourcing” or “conditional text” or some other variation on those themes. Same thing. It means that you, the author, manually “tag” the content for the different versions of the content that you publish. You maintain one version but publish many versions.

To my way of thinking, filtering is really a methodology or way of approaching content and authoring content. Once you grasp the concept of filtering, you can accomplish the actual tasks in many different tools: any number of XML editors using DITA, FrameMaker, or even Microsoft Word.

Generally speaking, filtering is easy to implement. But, we’ll explore more about that in another post. For now, an example!

Example

freeimage-6279867-high

Let’s say you make a robot product with the following features:

  • Pushes you out of bed
  • Makes your coffee
  • Turns on your computer
  • Checks your email
  • Asks Google what you should do today
  • Makes you a breakfast burrito
  • Drives the kids to school
  • Makes lunch
  • Makes dinner
  • Tells you a bedtime story

And you sell the robot in the following models. I’m going to color-code the shared items for you:

  • The 24/7 Robot
    • Includes all features except Tells you a bedtime story
  • The Morning Robot
    • Pushes you out of bed
    • Makes your coffee
    • Turns on your computer
    • Checks your email
    • Asks Google what you should do today
    • Makes you a breakfast burrito
    • Drives the kids to school
    • Makes lunch
  • The Mid-day Robot
    • Makes your coffee
    • Checks your email
    • Makes lunch
  • The Night Owl Plus Robot
    • Makes lunch
    • Makes dinner
    • Tells you a bedtime story
    • Pushes you out of bed

You need to create long, complex sales proposals, web content, and user guides for all of these versions. Wowsa. You’ll make that happen with content tagging. Read on.

Tagging

Tagging is the magic behind filtering. Using our robot example, let’s say you have an introductory section that lists all the features of your robot. Rather than maintain four different versions of the introductory section (24/7, Morning Person, Mid-day Person, and Night Owl), you would have ONE version in which the content is tagged for the different models. Like I said, magic.

Once again using our robot example, you would tag your introductory section as follows:

Our fantastic robot will revolutionize your entire life. Here's a list 
of its features: [this content not tagged because you want this text to show 
up in all versions]
  • Pushes you out of bed [tagged 24/7, Morning Person, and 
    Night Owl Plus] 
  • Makes your coffee [tagged 24/7, Morning Person, Mid-day Person]
  • Turns on your computer [tagged 24/7 and Morning Person]
  • Checks your email [tagged 24/7, Morning Person, Mid-day Person]
  • Asks Google what you should do today [tagged 24/7 and 
    Morning Person]
  • Makes you a breakfast burrito [tagged 24/7 and Morning Person]
  • Drives the kids to school [tagged 24/7 and Morning Person]
  • Makes lunch [not tagged because you want this 
    text to show up in all versions]
  • Makes dinner [tagged 24/7 and Night Owl Plus]
  • Tells you a bedtime story [tagged Night Owl Plus]

After you had tagged all the content, you would push a button in whatever tool you use to publish things (again, could be an XML editor, FrameMaker, Word, etc.), and that tool would spit out the version you want to see. More on that in another post.

Version Matrix

I’ve found it helpful to maintain a version matrix for my sanity. The matrix can also be helpful as a reference for other team members. Continuing with our example, the robot’s version matrix would look like this:

Screen Shot 2014-03-04 at 11.30.03 AM

Benefits

There are many benefits of filtering, but off the top of my head, here are some:

  • Produces reliable content every time. No more “Is this the version I put that improvement in a few weeks ago?”
  • Optimizes your content library. No more maintenance of ten slightly different versions.
  • You can show or not show whole topics, paragraphs, sentences, or a single letter (by tagging it).
  • You can produce many individual publications from one set of content files.
  • Bottom line is actually the bottom line: it saves time/money.

To be clear, the use case or need for filtering is only warranted in an environment in which you are already keeping multiple versions of the same content and using them in a variety of publications.

Start Slowly

As I mentioned earlier, filtering requires a mindset change. It takes some time to fully grasp and implement filtering. Start with one small project. In my next post, I’ll explain how to do that.

Feedback?

Are there posts out there that do a better job of explaining filtering? Please let me know in the comments. Also, any other comments and/or corrections are very welcome.

Report on March 12th Meeting

Last night’s meeting was almost entirely devoted to discussing conditional filtering, with a few digressions into conrefs, content management systems, and the local taco carts. Melanie Jennings shared her detailed planning process for tagging and filtering a set of DITA files that will currently support six different filtered outputs for different audiences and platforms, but in the future may have to support many more. We also heard about how other PDX DITA members are using conditional filtering in different ways to get the most out of their files, and discussed some of the challenges of ditamap inheritance, enforcing consistent tagging, and, especially, educating all the writers in a group who need to understand not only the tagging model but how and to whom the final output will be delivered.

We were excited to have Toni Mantych join us for the first time. Toni teaches DITA over at Portland State and is planning to teach a DITA workshop in May through the local STC chapter. Stay tuned for more news about that workshop in a future post.

If you’d like to attend the next meeting in June, please check back here for the date or contact us to be added to the email list for reminders.

Filtering Extravaganza!

For our next PDX DITA meeting, we are inviting attendees to bring in and show their filtering madness. Fun, right? If you don’t know what filtering is, this would be a perfect opportunity to pick the brains of local practitioners to see what and how we’re doing with filters.

We’d like to know:

  • How many topics do you have?
  • How many help sets do you deliver from those topics?
  • How many filter attributes do you use for those help sets?
  • What kinds of validation do you use to prevent logic failures?
  • What would you like to do with filters that you can’t do today? Examples encouraged.

As usual, we’ll be meeting at the lovely downtown offices of Jive Software in Portland. We are looking forward to meeting you and talking shop about DITA!