Author Archives: dpclark

QA Plugin: Solving for Attribute Chunk

Posted on by dpclark
Reply

The Issue

The @chunk="to-content" requirement for the QA plugin has always been a bit sticky. Honestly, I hadn’t thought much about it since we run the QA plugin through a self-service web server and that attribute is handled by a Python controller. However, thinking in terms of local builds, it became evident that setting the @chunk by hand would quickly become a tiresome routine.

Besides attribute handling, the web server also masks another consideration—the QA plugin may not be running in isolation from other plugins.

 The First Iteration

The first iteration of to move this functionality to the plugin itself resulted in a new build target extending the chunk preprocess.

In plugin.xml:

<feature extension="depend.preprocess.chunk.pre" value="setchunk"/>

The target in build_qadata.xml:

<target name="setchunk" description="Set @chunk to-content on the temp input bookmap" if="if.chunk">
<replace file="${dita.temp.dir}/${user.input.file}"
token="chunk=.to-content." value="" />
<replace file="${dita.temp.dir}/${user.input.file}"
token="&lt;bookmap " value="&lt;bookmap chunk='to-content' " />
<replace file="${dita.temp.dir}/${user.input.file}"
token="&lt;map " value="&lt;map chunk='to-content' " />
</target>

The new target used a regex replace to add the chunk attribute just before processing began in the temporary build directory. This solved the problem of manually setting the attribute, but also extended the chunk pre-processing to other sibling plugins as well.

The Solution

It’s possible to add an if-condition to a target to look for the presence of a command-line parameter, but I needed to look for a parameter with a specific value.  A second iteration added a double-hop if-condition to the ant call.

<condition property="if.chunk">
<equals arg1="${setchunk}" arg2="true" casesensitive="false" />
</condition>

<target name="setchunk" description="Set @chunk to-content on the temp input bookmap" if="if.chunk">
<replace file="${dita.temp.dir}/${user.input.file}"
token="chunk=.to-content." value="" />
<replace file="${dita.temp.dir}/${user.input.file}"
token="&lt;bookmap " value="&lt;bookmap chunk='to-content' " />
<replace file="${dita.temp.dir}/${user.input.file}"
token="&lt;map " value="&lt;map chunk='to-content' " />
</target>

This approach looks for the presence of the setchunk switch and a value of true before applying the target, which is called with:

dita -f qa -i samples/taskbook.ditamap -Dsetchunk=true

So if you run the QA plugin alongside any others, you can leave off the switch to avoid unwanted chunk attributes.

Posted in QA plugin | Leave a reply

QA Plugin XSLT: Locating Distinct Values for Duplicate IDs

Posted on by dpclark
2

As part of a new framework enhancement, I needed a method to ensure that certain DITA elements carried unique @id values. Our authoring tool does a good job identifying duplicate @id values within a topic, but does not indicate whether those values also exist in other topics referenced in the DITA map.

In this case, the best fit was to add a new check to the QA plugin.

The check should:

• Identify duplicate @id values on specific elements
• Return only distinct values (i.e. if 123 appears several times, then return 123 only once)

After some forum research, my first thought was to use a key match.

<xsl:key name="duplicateIds" match="elementName" use="@id" />

And reference it with

key('duplicateIds',@id)[2] and count(.|key('duplicateIds', @id)[1]) = 1

So the if statement for the check looked like

<xsl:for-each select="//parentElement">
<xsl:if test="key('duplicateIds',@id)[2] and count(.|key('duplicateIds', @id)[1]) = 1">
Remove duplicate elementName @id=<xsl:value-of select="@id"/>
</xsl:if>
</xsl:for-each>

Even though it met my requirements, it’s still an outdated approach that didn’t leave me with a job-well-done sense of completion. I wanted a cleaner solution that fit somewhere closer to the 2.0 realm.

I decided to use grouping to identify each distinct @id value. Then I could wrap an if statement to test for any groups that contained a second (duplicate) item. The result:

<xsl:for-each-group select="//elementName" group-by="@id">
<xsl:if test="current-group()[2]">
Remove duplicate elementName @id=<xsl:value-of select="@id"/>
</xsl:if>
</xsl:for-each-group>

Have a better approach? Leave a comment.

Posted in plugins, QA plugin, tools | Tagged 2.0, QA, XSLT | 2 Replies

Python, LXML, and setting xml:lang

Posted on by dpclark
Reply

Having trouble figuring out how to script the @xml:lang attribute?

For a DITA document that contains a single language, the highest level element (i.e. map, concept, task, etc.) that contains content should set the @xml:lang attribute to the language that applies to the document.

The question: How do I set the @xml:lang attribute using lxml? Everyone seems confused on the forums. Continue reading

Posted in authoring, tools | Tagged attributes, automation, dita, lxml, python, translation, xml | Leave a reply

Recursive DITA parsing using Perl and XML Twig, Part I

Posted on by dpclark
7

If you’re doing any text parsing and manipulation, it’s hard to ignore the processing power of Perl—especially considering that it comes pre-installed on the basic OS X platform.   There are several XML parsing modules out there and plenty of sites comparing the features and usability of each one.

Personally, I like Michael Rodriguez’s (mirod) Twig module.   It’s available on CPAN here. Continue reading

Posted in tools | 7 Replies

Automating useful tasks within a CMIS repository

Posted on by dpclark
6

I started a project a while back to curb some of the less-efficient tasks for my Alfresco-based CMS.  My main target: eliminate the painfully slow file check-in process.  My goal: create a per-user bulk check-in method.

If you’re curious about how far you can get with some fairly basic scripting gusto, a good place to start is with the Apache Chemistry project.  Continue reading

Posted in cms, tools | Tagged automation, CMIS, scripting | 6 Replies