Output filename based on variables

Post here questions and problems related to editing and publishing DITA content.
AndrewCampbell
Posts: 3
Joined: Tue Jul 16, 2019 5:17 pm

Output filename based on variables

Post by AndrewCampbell »

I'd like to be able to set the output base filename (the part specified by args.output.base) based on the value of some variables.

In my case, the mainbooktitle in each of my bookmaps consists of three ph elements which are in turn keyref'ed, something like this:

Code: Select all

<mainbooktitle>
        <ph keyref="Product"/> 
        <ph keyref="Release"/>
        <ph keyref="DocumentType/>
</mainbooktitle>
I would like the output filename to be something like "[value of Product]_[value of Release]_[value of DocumentType].pdf".

I can think of a few complex ways of making this happen by wrapping the DITA-OT in a shell script or something similar, but I'd prefer to do it as a regular plugin, especially as I could use a regular plugin within Oxygen. Is this possible?
Radu
Posts: 9162
Joined: Fri Jul 09, 2004 5:18 pm

Re: Output filename based on variables

Post by Radu »

Hi Andrew,

I see you already got some answers on the DITA Users List.
I do not have a clear idea how a plugin could do that, probably if the plugin would have some custom ANT target which would be called before the PDF is produced, it could call an XSLT script to process the DITA Map from the temporary files folder (which would already have the keyrefs expanded). Then it would use the result produced by the XSLT script to set the value of the "args.output.base" parameter in the ANT build file.

Another Oxygen-specific approach would be to edit the transformation scenario and in the "Parameters" tab set a value for the "args.output.base" parameter using Oxygen specific editor variables like "${xpath_eval(expression)} ":

https://www.oxygenxml.com/doc/versions/ ... bles.htmle

and try to use XPath to read the value for each key from the DITA Map where it is defined. But this would work only inside Oxygen.

Regards,
Radu
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com
horisonten
Posts: 29
Joined: Thu Nov 30, 2023 12:45 pm

Re: Output filename based on variables

Post by horisonten »

Sorry to revive the old thread. Not sure if it is best practice to revive old threads. To me it feels like it since there would be many very similar topics which would make it more convoluted and hard to find. This thread is one of the top Google results and exactly what I'm trying to achieve.

So I'm trying to do the exact same as the OP by using XPath in the "args.output.base".
I have a <bookmap/mainbooktitle> which contains three <ph> elements with keyrefs:

Code: Select all

<mainbooktitle>Product name <ph keyref="variable1"/>, <ph keyref="variable2"/>, <ph keyref="variable3"/>
But I cannot get this to be set as the PDF output file name.

If I try:

Code: Select all

${xpath_eval(//*[contains(@class, " bookmap/mainbooktitle ")])}
I get this fatal error:
xml:485: java.nio.file.InvalidPathException: Illegal char <<> at index 81: C:\Users\User\OxygenXMLEditor\NKT\out\pdf-css-html5\<mainbooktitle>Product name <ph keyref="variable1"/>, <ph keyref="variable2"/>, <ph keyref="variable3"/>
But this Xpath works in the XPath Builder and fetches the correct text.

And this:

Code: Select all

${xpath_eval(//*[contains(@class, " bookmap/mainbooktitle ")]/text())}
Gives a similar error:
485: java.nio.file.InvalidPathException: Illegal char <
But this Xpath works in the XPath Builder and fetches the correct text.


If I try this to at least get something in the file name:

Code: Select all

${xpath_eval(//*[contains(@class, " bookmap/mainbooktitle ")]/span[@keyref = "variable1"])}
There are no errors, but the file name is empty (".pdf"). This Xpath also works in the XPath Builder and fetches the correct text.

So what can be the issue here? Is the issue that the keyrefs are not available/resolved for the xpath function?
julien_lacour
Posts: 543
Joined: Wed Oct 16, 2019 3:47 pm

Re: Output filename based on variables

Post by julien_lacour »

Hello horisonten,

From what I tested, running the following XPath in Oxygen XPath/XQuery Builder view:

Code: Select all

//*[contains(@class, " bookmap/mainbooktitle ")]
Will return you "Product name , ," without expanded keys.
The XPath is evaluated after parsing the ditamap, before expanding conrefs and keyrefs (as you assumed).
This is why you get an error when using it from the args.output.base parameter.

Regards,
Julien
horisonten
Posts: 29
Joined: Thu Nov 30, 2023 12:45 pm

Re: Output filename based on variables

Post by horisonten »

julien_lacour wrote: Tue Jun 18, 2024 2:06 pm Hello horisonten,

From what I tested, running the following XPath in Oxygen XPath/XQuery Builder view:

Code: Select all

//*[contains(@class, " bookmap/mainbooktitle ")]
Will return you "Product name , ," without expanded keys.
The XPath is evaluated after parsing the ditamap, before expanding conrefs and keyrefs (as you assumed).
This is why you get an error when using it from the args.output.base parameter.

Regards,
Julien
Yes, sorry I was a bit vague. I cannot get the resolved keyrefs inte the Xpath builder. But I'm not getting errors and I see that the Xpath is pointing to the correct location.

So is there a workaround where I actually can use Xpath in the args.output.base to set the PDF file name dynamically? I'm using a ditaval to control the content of the <ph> elements in the mainbooktitle and would like to avoid manually setting the pdf name every time.
julien_lacour
Posts: 543
Joined: Wed Oct 16, 2019 3:47 pm

Re: Output filename based on variables

Post by julien_lacour »

Hello horisonten,

You could use a custom Ant build file which calls the default target then changes the PDF file name by calling the XPath query inside an XSLT stylesheet on either merged.xml or merged.html file:

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<project basedir="." default="dist">
  <!-- The DITA-OT default build file -->
  <import file="path/to/org.dita.base/build.xml"/>

  <target name="dist">
    <!-- Call the DITA-OT default target -->
    <antcall target="init"/>
    <!-- Change PDF file name -->
    <antcall target="change-pdf-name"/>
  </target>

  <target name="change-pdf-name">
    <!-- The files paths must be relative to the ditamap -->
    <xslt in="out/pdf-css-html5/book.merged.xml" out="out/pdf-css-html5/temp.txt">
      <style>
        <string>
          <![CDATA[
            <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
              xmlns:xs="http://www.w3.org/2001/XMLSchema"
              exclude-result-prefixes="xs"
              version="3.0">
              <xsl:output method="text"/>
              <xsl:template match="/">
                <xsl:value-of select="//*[contains(@class, ' bookmap/mainbooktitle ')]"/>
              </xsl:template>
            </xsl:stylesheet>
          ]]>
        </string>
      </style>
    </xslt>
    <loadfile property="title" srcFile="out/pdf-css-html5/temp.txt"/>
    <delete file="out/pdf-css-html5/temp.txt"/>
    <move file="out/pdf-css-html5/book.pdf" tofile="out/pdf-css-html5/${title}.pdf"/>
  </target>
</project>
Regards,
Julien
horisonten
Posts: 29
Joined: Thu Nov 30, 2023 12:45 pm

Re: Output filename based on variables

Post by horisonten »

Great, thank you very much! I got it to work when using a transformation scenario.
But I'm unable to find the solution for making it work when using a DITA-OT project file which is pointing to an .opt file.

How would I go about to make the Ant build file work when using a DITA-OT project file and .opt?
julien_lacour
Posts: 543
Joined: Wed Oct 16, 2019 3:47 pm

Re: Output filename based on variables

Post by julien_lacour »

Hello horisonten,

If you are using a DITA project file with an OPT file the only solution is to set the 'args.output.base' parameter for each deliverable: either from the OPT file or if you are using the same template for different deliverables directly in the DITA project file. The Ant build file is not available at this level and cannot be changed.

Regards,
Julien
horisonten
Posts: 29
Joined: Thu Nov 30, 2023 12:45 pm

Re: Output filename based on variables

Post by horisonten »

julien_lacour wrote: Thu Jun 20, 2024 9:40 am Hello horisonten,

If you are using a DITA project file with an OPT file the only solution is to set the 'args.output.base' parameter for each deliverable: either from the OPT file or if you are using the same template for different deliverables directly in the DITA project file. The Ant build file is not available at this level and cannot be changed.

Regards,
Julien
All right, fair enough.

Could you please add an improvement suggestion at least? It would be very handy to be able to easily set the output pdf filename based on <keyrefs> in the Mainbooktitle.
julien_lacour
Posts: 543
Joined: Wed Oct 16, 2019 3:47 pm

Re: Output filename based on variables

Post by julien_lacour »

Hello horisonten,

Sure, I added OPE-281 as improvement to set file names using args.output.base parameter and titles with keys.

Regards,
Julien
xephon
Posts: 146
Joined: Mon Nov 24, 2014 1:49 pm
Location: Greven/Germany

Re: Output filename based on variables

Post by xephon »

The way I solved this in the past is like so:
You add an Ant target after processing. There is the preprocessing.post extension point in the OT. After preprocessing, the keyrefs are resolved. In this target, read the temporary map and cherry pick what you want. Then save this in properties, maybe in a property file. Let the normal processing continue and call another target at the very end, read your properties and rename the PDF.
stefan-jung.org – Your DITA/DITA-OT XML consultant
Post Reply