Pass DITA Map Directory to Custom XSLT Refactoring Operation
Posted: Tue Apr 29, 2025 11:12 pm
Hi Oxygen Support,
My team wants a custom refactoring operation that converts "empty" or "stub" topics (topics whose body is empty) into topicheads.
To accomplish this, I wrote the following XSLT:
The idea being the XSLT goes into each topicref and checks whether or not the topic's body has child elements. If not, it converts the topicref into a topichead and uses the topic's title as the topichead's navtitle. Otherwise, it preserves the topicref as-is.
This works whenever I use Oxygen XML Editor's debugging Run operation; however, it doesn't seem to work when I run it as a refactoring operation. I'm suspecting it might have something to do with how the current DITA Map's file path is being captured.
I also attempted to define a parameter in the refactoring description file that would be used to specify the current file directory via the ${cfd} editor variable, and then pass this along to the XSLT, but this didn't work either. I believe it was because Oxygen wasn't expanding the ${cfd} variable and seemed to pass this value in as plain text.
Is there a way that I can supply the current DITA Map file directory to my refactoring XSLT so that the XSLT can walk through every referenced topic?
Thanks!
My team wants a custom refactoring operation that converts "empty" or "stub" topics (topics whose body is empty) into topicheads.
To accomplish this, I wrote the following XSLT:
Code: Select all
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:dita-ot="http://dita-ot.sourceforge.net/ns/201007/dita-ot"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:fn="http://www.playstation.com/functions"
xmlns:ditaarch="http://dita.oasis-open.org/architecture/2005/"
exclude-result-prefixes="xs dita-ot xsi fn ditaarch"
version="3.0">
<xsl:output doctype-public="-//OASIS//DTD DITA Map//EN" doctype-system="map.dtd"
indent="yes" method="xml"/>
<xsl:variable name="ditamap-path">
<xsl:value-of select="document-uri()"/>
</xsl:variable>
<xsl:variable name="resolved-ditamap-directory">
<xsl:value-of select="replace($ditamap-path, '\/[\w\.]*$', '', ';j')"/>
</xsl:variable>
<xsl:template match="*[contains(@class, ' map/topicref ')]">
<xsl:choose>
<xsl:when test="document(concat($resolved-ditamap-directory, '/', @href))//body//*">
<xsl:element name="topicref">
<xsl:apply-templates select="@*"/>
<xsl:if test="descendant::*[contains(@class, ' map/topicref ')]">
<xsl:for-each select="descendant::*[contains(@class, ' map/topicref ')]">
<xsl:call-template name="process-topicref"/>
</xsl:for-each>
</xsl:if>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:element name="topichead">
<xsl:attribute name="navtitle">
<xsl:value-of select="document(concat($resolved-ditamap-directory, '/', @href))/topic/title"/>
</xsl:attribute>
<xsl:if test="descendant::*[contains(@class, ' map/topicref ')]">
<xsl:for-each select="descendant::*[contains(@class, ' map/topicref ')]">
<xsl:call-template name="process-topicref"/>
</xsl:for-each>
</xsl:if>
</xsl:element>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="process-topicref">
<xsl:choose>
<xsl:when test="document(concat($resolved-ditamap-directory, '/', @href))//body//*">
<xsl:element name="topicref">
<xsl:apply-templates select="@*"/>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:element name="topichead">
<xsl:attribute name="navtitle">
<xsl:value-of select="document(concat($resolved-ditamap-directory, '/', @href))/topic/title"/>
</xsl:attribute>
</xsl:element>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="@class | @domains | @xtrf | @xtrc | @ditaarch:DITAArchVersion"
priority="10"/>
<xsl:template match="processing-instruction('workdir') |
processing-instruction('workdir-uri') |
processing-instruction('path2project') |
processing-instruction('path2project-uri') |
processing-instruction('ditaot') |
processing-instruction('doctype-public') |
processing-instruction('doctype-system') |
@dita-ot:* |
@mapclass"
priority="10"/>
<xsl:template match="*[number(@ditaarch:DITAArchVersion) < 1.3]/@cascade"/>
<xsl:template match="*[@class]" priority="-5">
<xsl:element name="{tokenize(tokenize(normalize-space(@class), '\s+')[last()], '/')[last()]}"
namespace="{namespace-uri()}">
<xsl:apply-templates select="node() | @*"/>
</xsl:element>
</xsl:template>
<xsl:template match="*" priority="-10">
<xsl:element name="{name()}" namespace="{namespace-uri()}">
<xsl:apply-templates select="node() | @*"/>
</xsl:element>
</xsl:template>
<xsl:template match="node() | @*" priority="-15">
<xsl:copy copy-namespaces="no">
<xsl:apply-templates select="node() | @*"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
This works whenever I use Oxygen XML Editor's debugging Run operation; however, it doesn't seem to work when I run it as a refactoring operation. I'm suspecting it might have something to do with how the current DITA Map's file path is being captured.
I also attempted to define a parameter in the refactoring description file that would be used to specify the current file directory via the ${cfd} editor variable, and then pass this along to the XSLT, but this didn't work either. I believe it was because Oxygen wasn't expanding the ${cfd} variable and seemed to pass this value in as plain text.
Is there a way that I can supply the current DITA Map file directory to my refactoring XSLT so that the XSLT can walk through every referenced topic?
Thanks!