Re: [xsl] Flatten DITA conrefs

Subject: Re: [xsl] Flatten DITA conrefs
From: "rick@xxxxxxxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Fri, 11 Apr 2025 22:24:44 -0000
Thanks for the input, Martin. One of the influential programming books I read
was, bJavaScript: The Good Partsb and his counsel was to be as explicit as
possible when programming so I like to use true() and false() when making
comparisons. id values are not required on all DITA elements, so I am not sure
if the id() function will work here. Thanks again.



From: Martin Honnen martin.honnen@xxxxxx
<xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Sent: Friday, April 11, 2025 6:07 PM
To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
Subject: Re: [xsl] Flatten DITA conrefs



On 11/04/2025 21:21, rick@xxxxxxxxxxxxxx <mailto:rick@xxxxxxxxxxxxxx>  wrote:

Hi All,



I am working with a DITA transformation and I want to flatten some conrefs. I
have created a function to do this, and it is working, but I am looking for
feedback to see if there is a better approach. Here is my XML:



<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE concept

  PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">

<concept id="ConrefTest-GAC500-B-15-30-27-02A-131C-A">

    <title>Conref Test</title>

    <conbody>

        <section>

            <title>Possible Cause</title>

            <p>

                <ph

                conref="CASMessages.dita#cas-messages/AFM-L-R-CAI-Selected-Of
f-status"

                outputclass="cas-status"/>

            </p>

        </section>

    </conbody>

</concept>



Here is my XSLT. If the conref doesnbt resolve, I am just passing the parent
element through as is.



<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet xmlns:xsl= <http://www.w3.org/1999/XSL/Transform>
"http://www.w3.org/1999/XSL/Transform";

    xmlns:xs= <http://www.w3.org/2001/XMLSchema>
"http://www.w3.org/2001/XMLSchema";

    xmlns:cp= <http://www.frameexpert.com/functions/cp>
"http://www.frameexpert.com/functions/cp";

    exclude-result-prefixes="xs cp"

    version="3.0" expand-text="yes">



    <xsl:output indent="yes"/>



    <xsl:template
match="entry/ph[matches(@conref,'CASMessages','i')=true()]">

        <xsl:sequence select="cp:flattenConref(current())"/>

    </xsl:template>



    <xsl:mode on-no-match="shallow-copy"/>



    <xsl:function name="cp:flattenConref">

        <xsl:param name="ph"/>

        <!-- Split the conref to get the target file. -->

        <xsl:variable name="conrefData" select="tokenize($ph/@conref,'#')"/>

        <xsl:choose>

            <!-- Make sure there is a file and it is available on disk. -->

            <xsl:when test="count($conrefData)=2">

                <xsl:variable name="file"
select="resolve-uri($conrefData[1],base-uri($ph))"/>

                <xsl:choose>

                    <xsl:when test="doc-available($file)=true()">

                        <!-- Get the target id from the conref. -->

                        <xsl:variable name="id"
select="tokenize($conrefData[2],'/')[last()]"/>

                        <xsl:choose>

                            <!-- See if the target element exists. -->

                            <xsl:when test="doc($file)//*[@id=$id]">

                                <!-- Return the conref's value. -->

                                <ph
outputclass="{$ph/@outputclass}"><xsl:sequence
select="doc($file)//*[@id=$id]/text()"/></ph>

                            </xsl:when>

                        </xsl:choose>

                    </xsl:when>

                    <!-- The conref file does not exist; return the ph
element. -->

                    <xsl:otherwise><xsl:sequence
select="$ph"/></xsl:otherwise>

                </xsl:choose>

            </xsl:when>

            <!-- No # anchor; return the ph element. -->

            <xsl:otherwise><xsl:sequence select="$ph"/></xsl:otherwise>

        </xsl:choose>

    </xsl:function>



</xsl:stylesheet>



Two small comments, I never get why people use a comparison to true or false,
I would just go with e.g.

  xsl:template match="entry/ph[matches(@conref,'CASMessages','i')]"

and

  xsl:when test="doc-available($file)"



And I wonder whether DITA sets up the id attribute as a DTD ID or schema xs:ID
so that instead of

  doc($file)//*[@id=$id]

you could use e.g.

  id($id, doc($file))





XSL-List info and archive <http://www.mulberrytech.com/xsl/xsl-list>

EasyUnsubscribe <http://lists.mulberrytech.com/unsub/xsl-list/612310>  (by
email <> )

Current Thread