1
votes

With XSL-FO I want to publish dynamic links to a PDF file. I found here on StackOverflow and with google many examples with a static url, but no example with a dynamic url. That's why I post this question. I want to generate the link from a xml file (the link is the value of the attribute 'href' in the element 'topicref'):

<?xml version="1.0" encoding="utf-8"?>
<map outputclass="DTVMap">
<title>Testdocument DTVmap</title>
<topicref format="dita" scope="local" href="ObjSt/bla/DTV/Testdocument_14.06.dita" navtitle="Testdocument 14.06" />
</map>

I used in the xsl-fo:

<fo:basic-link external-destination="url(<xsl:value-of select="map/topicref/@href"/>)" color="blue" text-
decoration="underline"><xsl:value-of select="map/topicref/@href"/></fo:basic-link>

And I get a message that: "The value of attribute "external-destination" associated with an element type "null" must not contain the '<' character."

I tried to get the link with adding the code below in the xsl-fo instead of the 'basic-link external-destination' from above.

<xsl:value-of select="map/topicref/@href"/>
<xsl:param name="link" select="map/topicref/@href" />
<fo:basic-link color="blue" text-decoration="underline">
<xsl:attribute name="external-destination">
<xsl:value-of select="$link" />
</xsl:attribute>
<xsl:value-of select="$link" />
</fo:basic-link>

There is a link in the generated PDF now, but the link is: 'file:///C/ws/fo_xslt/ObjSt/bla/DTV/Testdocument_14.06.dita' in stead of: 'ObjSt/bla/DTV/Testdocument_14.06.dita'.

The question is; how can I get a link like: 'ObjSt/bla/DTV/Testdocument 14.06.dita' so, without 'file:///C/ws/fo_xslt'? 'C:/ws/fo_xslt' is the directory where I put the generated PDF. Or: How can I get the link which only contains the value of the href attribute? Thanks

PS: The Java class I use in order to generate a pdf is (just to give some more background):

package foXslt;

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;

import javax.xml.transform.Result;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.apache.fop.apps.*;

public class FopPdf {

    public static void main(String[] args) {
    FopPdf fOPPdfDemo = new FopPdf();
        try {
            fOPPdfDemo.convertToPDF();
        } catch (FOPException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (TransformerException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }


    /**
     * Method that will convert the given XML to PDF
     * @throws IOException
     * @throws FOPException
     * @throws TransformerException
     */
    public void convertToPDF()  throws IOException, FOPException, TransformerException {
        // the XSL FO file
        File xsltFile = new File("C:\\ws\\fo_xslt\\foxslt.xsl");
        // the XML file which provides the input
        StreamSource xmlSource = new StreamSource(new File("C:\\ws\\fo_xslt\\xmlDTVMapMetLink.xml"));
        // create an instance of fop factory
        FopFactory fopFactory = FopFactory.newInstance(new File(".").toURI());
        // a user agent is needed for transformation
        FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
        // Setup output
        OutputStream out;
        out = new java.io.FileOutputStream("C:\\ws\\fo_xslt\\foxslt.pdf");

        try {
            // Construct fop with desired output format
            Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, out);

            // Setup XSLT
            TransformerFactory factory = TransformerFactory.newInstance();
            Transformer transformer = factory.newTransformer(new StreamSource(xsltFile));

            // Resulting SAX events (the generated FO) must be piped through to FOP
            Result res = new SAXResult(fop.getDefaultHandler());

            // Start XSLT transformation and FOP processing
            // That's where the XML is first transformed to XSL-FO and then
            // PDF is created
            transformer.transform(xmlSource, res);
        } finally {
            out.close();
        }
    }
1
How did you confirm that generated link is 'file:///C/ws/fo_xslt/ObjSt/bla/DTV/Testdocument_14.06.dita'? Is it Adobe Reader's display result? I think Reader usually recognize relative path as based from PDF existing folder.tmakita
'ObjSt/bla/DTV/Testdocument 14.06.dita' is the relative path notation. What absolute path do you want generate from this?tmakita

1 Answers

1
votes

Simplest way would be to use an attribute value template. Use { and } around the expression that you want to evaluate:

<fo:basic-link external-destination="url({map/topicref/@href})"
    color="blue" text-decoration="underline">
  <xsl:value-of select="map/topicref/@href"/>
</fo:basic-link>

See https://www.w3.org/TR/xslt#attribute-value-templates for the XSLT 1.0 definition.