Subject: Re: [xsl] Flatten DITA conrefs From: "Michael Kay michaelkay90@xxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> Date: Sat, 12 Apr 2025 07:50:19 -0000 |
>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. There's something to be said for avoiding reliance on "effective boolean value" conversions, but when you're testing the result of a function like matches() or doc-available() that always returns a boolean, it makes very little sense. You wouldn't (I hope) write `test="(@x = 2) = true()"`. I would encourage you to declare the parameter type and result type of the function. (Both as="element(ph)", I think). This might point out that when the innermost xsl:when condition is false, there is no xsl:otherwise so you are returning an empty sequence. I don't know if that's what you intended. I would be inclined to write > <xsl:function name="cp:flattenConref" as="element(ph)"> > <xsl:param name="ph" as="element(ph)"/> > <!-- Split the conref to get the target file. --> > <xsl:variable name="conrefData" select="tokenize($ph/@conref,'#')"/> <xsl:variable name="result" as="element(ph)?"> > > <!-- Make sure there is a file and it is available on disk. --> > <xsl:if test="count($conrefData)=2"> > <xsl:variable name="file" select="resolve-uri($conrefData[1],base-uri($ph))"/> > <xsl:if test="doc-available($file)=true()"> > <!-- Get the target id from the conref. --> > <xsl:variable name="id" select="tokenize($conrefData[2],'/')[last()]"/> <xsl:variable name="target" select="doc($file)//*[@id=$id]"/> > > <!-- See if the target element exists. --> > <xsl:if test="exists($target)"> > <!-- Return the conref's value. --> > <ph outputclass="{$ph/@outputclass}"><xsl:sequence select="$target/text()"/></ph> > </xsl:if>> > </xsl:if> </xsl:variable> <xsl:sequence select="($result, $ph)[1]"/> > </xsl:function> > 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-Off-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 <>) > XSL-List info and archive <http://www.mulberrytech.com/xsl/xsl-list> > EasyUnsubscribe <http://lists.mulberrytech.com/unsub/xsl-list/3500899> (by email <>)
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] Flatten DITA conrefs, rick@xxxxxxxxxxxxxx | Thread | Re: [xsl] Flatten DITA conrefs, rick@xxxxxxxxxxxxxx |
Re: [xsl] Flatten DITA conrefs, rick@xxxxxxxxxxxxxx | Date | Re: [xsl] Flatten DITA conrefs, Toshihiko Makita tma |
Month |