Topics

seeking tips/advise/resources for transforming DITA topics to JSON #JSON

Tracy Baker <t.baker@...>
 

so we can feed tooltips to our UI.

 

We can’t be the only ones trying to do this, so I seek the wisdom of the DITA-users hive :)

Thanks!

Tracy

 

 

ekimber@contrext.com
 

XSLT 3, which is supported by the version of Saxon included with OT 3.x, includes the ability to write JSON as one of the built-in output methods.

This makes it pretty easy to write JSON from XSLT.

There are a number of plugins out there that do very little, so if you're just looking to extract specific text from your topics, something like the built-in troff plugin might be a good place to start, or maybe Robert Anderson has a better suggestion for a starting point.

Cheers,

Eliot
--
Eliot Kimber
http://contrext.com


On 6/26/19, 5:49 PM, "Tracy Baker t.baker@... [dita-users]" <dita-users@...> wrote:
so we can feed tooltips to our UI.

We can’t be the only ones trying to do this, so I seek the wisdom of the DITA-users hive :)
Thanks!
Tracy

Radu Coravu
 

Hi,

Somehow maybe this could be thought out the other way around.
Keep the UI strings in JSON as the native format and then have a DITA Open Toolkit plugin which has a pre-processing stage converting the JSON to a DITA topic containing reusable content.
Then reuse the UI strings in other DITA topics.

Regards,
Radu

Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com

On 6/27/2019 2:42 AM, Eliot Kimber ekimber@... [dita-users] wrote:
XSLT 3, which is supported by the version of Saxon included with OT 3.x, includes the ability to write JSON as one of the built-in output methods.

This makes it pretty easy to write JSON from XSLT.

There are a number of plugins out there that do very little, so if you're just looking to extract specific text from your topics, something like the built-in troff plugin might be a good place to start, or maybe Robert Anderson has a better suggestion for a starting point.

Cheers,

Eliot
--
Eliot Kimber
http://contrext.com


On 6/26/19, 5:49 PM, "Tracy Baker t.baker@... [dita-users]" <dita-users@...> wrote:
so we can feed tooltips to our UI.

We can’t be the only ones trying to do this, so I seek the wisdom of the DITA-users hive :)
Thanks!
Tracy
















------------------------------------
Posted by: Eliot Kimber <ekimber@...>
------------------------------------


------------------------------------

Yahoo Groups Links


despopoulos_chriss
 

You are not the only ones doing this.  We transform DITA to JSON to feed topics into bootstrap tour widgits.  It includes specific data elements that map to the CSS selector so the tour balloon points to the correct item in the GUI, and other settings that can actually change the URL for the given view.  So what we're doing is more elaborate than tooltips, but along the same lines. 

Probably the one thing I found necessary is that you need a special token for quotes, and then you turn that into actual quote characters later.  This is probably XSLT ignorance on my part, but it works -- I won't fix it. 

The idea is to turn your DITA into a specific array of JSON objects, based on specific elements in the DITA.  One thing that's tricky is is following each object in the array with a comma...  except the last one.  You will need to play around before you will get valid JSON.  Start small and keep trying.

We actually do this live in the GUI, performing the transform in the browser.  So it's all XSLT 1.0.  Our GUI is in Angular, and we have some services that can perform any DITA transform that you want.  THis is just one of them.

Assuming the forum allows it, here's the XSLT for turning a topic with a list of steps into a series of tour balloons (warts and all).  Some stuff might be special-case for us, but you can see the picture:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                version="1.0">

    <xsl:output method="text"  indent="no"/>

    <xsl:param name="dv_vals"/>
    <xsl:param name="dv_attr"/>

    <!-- Ignore these element -->
    <xsl:template match="*[data/@value = 'page']"/>

    <xsl:template match="topic/title"/>
    <xsl:template match="shortdesc"/>

    <xsl:template match="ph">
        <xsl:choose>
            <xsl:when test="@keyref">
                <xsl:text>#KEY_WORD:</xsl:text><xsl:value-of select="@keyref"/><xsl:text>#</xsl:text>
            </xsl:when>
            <xsl:otherwise>
                <xsl:text>&lt;ph&gt;</xsl:text>
                <xsl:apply-templates/>
                <xsl:text>&lt;/ph&gt;</xsl:text>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
   


    <xsl:template match="topic">
        <xsl:copy>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>
   
    <xsl:template match="body">
        <xsl:text>[</xsl:text>
        <xsl:apply-templates/>
        <xsl:text>]</xsl:text>
    </xsl:template>
   
    <xsl:template match="section">
        <xsl:choose>
            <xsl:when test="./data[@name='component' and @value='Overview']">
                    <xsl:text>{</xsl:text> <!-- Start the first tour object -->
                    <!-- Get the metadata -->
                    <xsl:for-each select="./data">
                        <xsl:text>CUD_OPENQUOTE</xsl:text>
                        <xsl:value-of select='@name'/>
                        <xsl:text>CUD_CLOSEQUOTE : CUD_OPENQUOTE</xsl:text>
                        <xsl:value-of select='@value'/>
                        <xsl:text>CUD_CLOSEQUOTE, </xsl:text>
                    </xsl:for-each>
                    <!-- Now get title and content -->
                    <xsl:text>CUD_OPENQUOTEtitleCUD_CLOSEQUOTE : CUD_OPENQUOTE</xsl:text>
                    <xsl:value-of select='../../title'/>
                    <xsl:text>CUD_CLOSEQUOTE, CUD_OPENQUOTEcontentCUD_CLOSEQUOTE : CUD_OPENQUOTE</xsl:text>
                    <xsl:apply-templates/>
                    <!-- Finish this object. Assume it's followed by another! -->
                    <xsl:text>CUD_CLOSEQUOTE},</xsl:text>
            </xsl:when>
            <xsl:otherwise>
                <xsl:apply-templates/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

    <xsl:template match="ol">
        <xsl:choose>
            <xsl:when test="../data[@name='component' and @value='Overview']">
                <xsl:text>&lt;ol&gt;</xsl:text>
                <xsl:apply-templates/>
                <xsl:text>&lt;/ol&gt;</xsl:text>
            </xsl:when>
            <xsl:otherwise>
                <xsl:apply-templates/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

    <xsl:template match="li">
        <xsl:choose>
            <xsl:when test="../../data[@name='component' and @value='Overview']">
                <xsl:text>&lt;li&gt;</xsl:text>
                <xsl:apply-templates/>
                <xsl:text>&lt;/li&gt;</xsl:text>
            </xsl:when>
            <xsl:when test="parent::ul">
                <xsl:text>&lt;li&gt;</xsl:text>
                <xsl:apply-templates/>
                <xsl:text>&lt;/li&gt;</xsl:text>
            </xsl:when>
            <xsl:otherwise>
                <xsl:text>{</xsl:text>
                <xsl:for-each select="./data">
                    <xsl:text>CUD_OPENQUOTE</xsl:text>
                    <xsl:value-of select='@name'/>
                    <xsl:text>CUD_CLOSEQUOTE : CUD_OPENQUOTE</xsl:text>
                    <xsl:value-of select='@value'/>
                    <xsl:text>CUD_CLOSEQUOTE, </xsl:text>
                </xsl:for-each>
                <xsl:apply-templates/>
                <xsl:text>CUD_CLOSEQUOTE}</xsl:text>
                <xsl:if test="./following-sibling::li"><xsl:text>,</xsl:text></xsl:if>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

    <!-- Start tour object for a given OL item -->
    <!-- Top level ol in a section is the list of tour balloons. -->
    <xsl:template match="topic/body/section/ol/li/p[position()=1]">
        <xsl:text>CUD_OPENQUOTEtitleCUD_CLOSEQUOTE : CUD_OPENQUOTE</xsl:text>
        <xsl:apply-templates/>
        <xsl:text>CUD_CLOSEQUOTE, CUD_OPENQUOTEcontentCUD_CLOSEQUOTE : CUD_OPENQUOTE</xsl:text>
    </xsl:template>

    <!-- Standard transforms of content into HTML to display as tour obj content -->
    <xsl:template match="p">
        <!-- The first pgf in an ol/li has already been turned into a title prop in the JSON. -->
        <xsl:if test="not(topic/body/section/ol/li/p[position()=1])">
            <xsl:text>&lt;p&gt;</xsl:text>
            <xsl:apply-templates/>
            <xsl:text>&lt;/p&gt;</xsl:text>
        </xsl:if>
    </xsl:template>

    <xsl:template match="note">
        <xsl:text>&lt;hr/&gt;</xsl:text>
        <xsl:text>NOTE:&lt;b/&gt; </xsl:text>
        <xsl:apply-templates/>
        <xsl:text>&lt;hr/&gt;</xsl:text>
    </xsl:template>

    <xsl:template match="ul">
        <xsl:text>&lt;ul&gt;</xsl:text>
        <xsl:apply-templates/>
        <xsl:text>&lt;/ul&gt;</xsl:text>
    </xsl:template>

    <xsl:template match="codeblock">
        <xsl:text>&lt;div class="codeblock"&gt;</xsl:text>
        <xsl:apply-templates/>
        <xsl:text>&lt;/codeblock&gt;</xsl:text>
    </xsl:template>

    <xsl:template match="b">
        <xsl:text>&lt;strong&gt;</xsl:text>
        <xsl:apply-templates/>
        <xsl:text>&lt;/strong&gt;</xsl:text>
    </xsl:template>

    <xsl:template match="i">
        <xsl:text>&lt;emphasis&gt;</xsl:text>
        <xsl:apply-templates/>
        <xsl:text>&lt;/emphasis&gt;</xsl:text>
    </xsl:template>

    <xsl:template match="codeph">
        <xsl:text>&lt;code&gt;</xsl:text>
        <xsl:apply-templates/>
        <xsl:text>&lt;/code&gt;</xsl:text>
    </xsl:template>

    <xsl:template match="text()">
        <xsl:choose>
            <!-- Section titles are stored as a title property, not part of content -->
            <xsl:when test="(ancestor::section) and (parent::title)">
                <!-- Skip... do nothing... -->
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="." />
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

</xsl:stylesheet>