FOP XSL-FO Internal page anchor link URI problems - xslt

Morning folks!
So I am currently working on an FOP solution for a project, the end goal of which is basically to allow me to print onto a medium with the second iteration of the same information upside down, a feature which is not possible in Access 2007.
Everything is working swimmingly, and I can get the FOP to parse when I duplicate the code for the front side and use it for the back side.
However, when I try to use the parameter, I am getting an error I simply don't understand from the FOP terminal, having spent the better part of 4-5 hours trying to get my head around it. Code and error to follow.
<?xml version="1.0" encoding="utf-8"?>
<!-- WARNING - THIS TEMPLATE IS FOR Z FOLD CANON STOCK - DOUBLE SIDED -->
<!-- In order to covert CM to pixels, multiply the CM by 37.7952755905511, and round to two decimal places. It may be easier to use a spreadsheet to do this if you are editing multiple values -->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:template match="/">
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<!-- EDIT THIS ROW TO CHANGE THE SIZE OF THE PAGE - AKA SET THIS TO THE SIZE OF THE MEDIUM YOU ARE PRINTING TO - CONVERTED TO PIXELS-->
<fo:simple-page-master master-name="simple" page-height="740.787px" page-width="317.480px">
<!-- IGNORE EVERYTHING BETWEEN HERE-->
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="simple">
<fo:flow flow-name="xsl-region-body">
<xsl:for-each select="//Person">
<fo:block>
<fo:instream-foreign-object>
<!--<svg xmlns="http://www.w3.org/2000/svg">-->
<!-- AND HERE-->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="370.4" height="634.96">
<g class="mirrorpage">
<rect style= "fill:none; stroke: black" width="370.394" height="317.480"/>
<text x="37.8" y="122.83" style="text-anchor:start;" font-family="'ChevinLight'">
<tspan font-size="20">
Firstname
</tspan>
<tspan font-size="20">
Lastname
</tspan>
</text>
<text style="text-anchor:start;" x="37.8" y="150" font-family="'ChevinLight'">
<tspan font-size="20">
Company Name
</tspan>
</text>
<xsl:variable name="code" select="Code"/>
<image xlink:href="LINK REDACTED" x="37.8" y="190" height="50" width="50"/>
<image xlink:href="LINK REDACTED" x="250" y="200" height="100"width="100"/>
</g>
<use href= "#mirrorpage" transform="translate (370.394 634.96) scale (-1 -1)"/>
</svg>
</fo:instream-foreign-object>
</fo:block>
</xsl:for-each>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
</xsl:stylesheet>
The error I am then receiving when I try to parse this is as follows:
[ERROR] svg graphic could not be built: file:/C:/Users/Events/Desktop/Angledtext/BadgePrinting/PDF/:-1
The URI '' specified on the element is invalid.
From my (limited) understanding, there is an issue with the parsing of the "#" in the use line. I have tried to research URI properties but I have to be honest, I am completely lost.
Any help, or even a pointer to some relevant material I can read would be greatly appreciated.
Thanks

Related

Apache FOP XSLT with svg-text render quality chaged after batik library upgrade

We recently migrated from FOP 2.1 to FOP 2.6 and witnessed a change in PNG output quality.
In our application fop is used with antialiasing OFF and in fop2.1 ( +batik 1.8) the text output is rendered nicely with no antialiasing .
But after we upgraded to FOP 2.6, PNG output is generated with antialiasing, without considering the fop.xconf setting or the text-rendering settings.
FOP 2.1 - Batik 1.8 output
FOP 2.6 - Batik 1.14 output
I tried various options by setting different text-rendering values but not able to get the same quality any more. I tried different versions of Batik lib and it seems that this change is seen from v1.9 onwards.
Seems like batik is ignoring anti-aliasing OFF configuration from the fop.xconf .
fop.xconf
<?xml version="1.0"?>
<fop version="1.0">
<complex-scripts disabled="false"/>
<renderers>
<renderer mime="image/png">
<color-mode>rgb</color-mode>
<transparent-page-background>false</transparent-page-background>
<background-color>white</background-color>
<anti-aliasing>false</anti-aliasing>
<rendering>false</rendering>
<fonts>
</fonts>
</renderer>
</renderers>
</fop>
Sample XSL
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" exclude-result-prefixes="fo">
<xsl:output method="xml" version="1.0" omit-xml-declaration="no" indent="yes"/>
<xsl:param name="versionParam" select="'1.0'"/>
<xsl:template match="articles[#page=1]">
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master master-name="simpleA4" page-height="168px" page-width="384px">
<fo:region-body /> <!-- background-color="#FFFF00" -->
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="simpleA4">
<fo:flow flow-name="xsl-region-body">
<!-- Temporarily Unavailable -->
<fo:block-container position="absolute" overflow="visible">
<fo:block>
<fo:instream-foreign-object xmlns:svg="http://www.w3.org/2000/svg">
<svg xmlns="http://www.w3.org/2000/svg" height="100" width="240" viewport="10 10 290 200">
<text x="150" y="20" fill="black" text-anchor="start" font-size="22pt" text-rendering="optimizeLegibility">STWOA</text>
</svg>
</fo:instream-foreign-object>
</fo:block>
</fo:block-container>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
</xsl:stylesheet>
Any help or hints would be highly appreciated !

How to transform XHTML+CSS with embedded images to XSL-FO?

I'm trying to transform a simple HTML page to XSL-FO, to feed into Apache FOP for PDF rendering.
The steps are: HTML+CSS -> XHTML -> XSL-FO -> PDF.
I've used the java library CSSToXSLFO to transform XHTML to XSL-FO. This works, however it's incapable of handling embedded images.
Are there any tools to transform
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>hello</title>
</head>
<body>
<h1 style="color: green">Hello world!</h1>
<img src="data:image/png;base64,iVBORw...=" />
</body>
</html>
into
<fo:flow flow-name="xsl-region-body">
<fo:block>
<fo:block color="green">Hello world!</fo:block>
<fo:external-graphic src="url(data:image/png;base64,iVBORw...=)" content-height="scale-to-fit" content-width="scale-to-fit" scaling="uniform"/>
</fo:block>
</fo:flow>
?
If the FOP processor supports data URIs in fo:external-graphic you can of course use XSLT to transform XHTML to XSL-FO with e.g.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
xpath-default-namespace="http://www.w3.org/1999/xhtml"
exclude-result-prefixes="#all"
version="3.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master master-name="sample">
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="sample">
<xsl:apply-templates select="html/body"/>
</fo:page-sequence>
</fo:root>
</xsl:template>
<xsl:template match="body">
<fo:flow flow-name="xsl-region-body">
<fo:block>
<xsl:apply-templates/>
</fo:block>
</fo:flow>
</xsl:template>
<xsl:template match="h1">
<fo:block>
<xsl:apply-templates/>
</fo:block>
</xsl:template>
<xsl:template match="img">
<fo:external-graphic src="{#src}" content-height="scale-to-fit" content-width="scale-to-fit" scaling="uniform"/>
</xsl:template>
</xsl:stylesheet>
That is a minimal example to handle the h1 and the img element, I haven't tried to spell out any HTML CSS style attribute to XSL-FO presentational attribute transformation but you can of course use e.g. <xsl:apply-templates select="#*, node()"/> instead of <xsl:apply-templates/> and then add templates to transform e.g. style="color: green" to color="green". As CSS has its own, non-XML syntax, obviously writing a full parser for arbitrary style attributes is a demanding task beyond the scope of StackOverflow answers.
I am also not quite sure about the allowed src attribute syntax in XSL-FO, FOP seems to understand the direct src="{#src}" just fine, but of course, to create the format you indicated in your question, you could as well use src="url({#src})".

viewing svg sprites with xslt

My team's designer has us using SVG "sprites" in our application. I'm want to be able to see all the available images. I was going to parse the XML and build something on the back end but then I thought about XSLT. I'd like to have an XSLT file that parses the SVG and creates a list of images. I'm close to getting it... here's what I have.
Sample SVG (although I also tried the sample file in the post):
<?xml-stylesheet type="text/xsl" href="/pages/sprites.xslt" ?>
<svg xmlns="http://www.w3.org/2000/svg">
<defs>
<symbol id="fitness" viewBox="0 0 64 64">
<g fill="none" fill-rule="evenodd" stroke-width="2" transform="translate(5 3)" stroke-linecap="square">
<path d="M5.8,27.0664159 L5.8,10.6333223 C5.8,4.7607008 10.5607008,0 16.4333223,0 L16.4333445,0 C22.3059668,0 27.0666667,4.7607008 27.0666667,10.6333223 L27.0666667,47.3666778 C27.0666667,53.2393002 31.8273665,58 37.699989,58 L37.7000111,58 C43.5726335,58 48.3333333,53.2393002 48.3333333,47.3666777 L48.3333333,30.9333333"/>
<polygon points="11.6 50.267 11.6 47.367 9.667 44.467 9.667 32.867 11.6 29.967 11.6 27.067 0 27.067 0 29.967 1.933 32.867 1.933 44.467 0 47.367 0 50.267"/>
<polygon points="54.133 30.933 54.133 28.033 52.2 25.134 52.2 13.533 54.133 10.633 54.133 7.733 42.533 7.733 42.533 10.633 44.467 13.533 44.467 25.134 42.533 28.033 42.533 30.933"/>
</g>
</symbol>
</defs>
</svg>
and the XSLT file found here:
How can I show all symbols in an SVG file?
It mostly works... it creates all the dom objects I'm expecting out of the box, which is pretty amazing. But inside use I get:
#shadow-root (closed)
which is what we see in our actual app... but in our app, the image is nested inside the shadow-root. But in this version, it's empty. Seems basically the same as how we're doing it on the app side. What's the issue?
Instead of loading the symbols from a file, write them into the output and reference locally.
Aditionally, you need to define a size for the used elements (the default would be 100%). As position() is one-based, subtract one to start top-left with the display.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns="http://www.w3.org/2000/svg"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<xsl:template match="/">
<svg>
<xsl:copy>
<xsl:copy-of select="//svg:defs"/>
</xsl:copy>
<g stroke="black" fill="black">
<xsl:for-each select="//svg:symbol">
<use width="32" height="32">
<xsl:attribute name="x"><xsl:value-of select="(position()-1) mod 10 * 32"/></xsl:attribute>
<xsl:attribute name="y"><xsl:value-of select="floor((position()-1) div 10) * 32"/></xsl:attribute>
<xsl:attribute name="xlink:href">#<xsl:value-of select="#id"/></xsl:attribute>
</use>
</xsl:for-each>
</g>
</svg>
</xsl:template>
</xsl:stylesheet>

hyphenation character in xslt attribute (xsl-fo)

I think it's a very simple question. But although I build very fancy xslt transformation, this simple one cannot be solved by me.
The problem is:
I want to add attributes to xsl-fo nodes, depending on xml data. These attributes have often a hyphen in it. How can I add these with an xslt transformation where xsl:attributes doesn't like the hyphenation character.
In a xml node I have got two attributes (name and value)
Example: name="font_size", value="7pt"
<Report>
<text content="I am a text">
<blockFormat name="font_size" value="7pt" />
</text>
</Report>
(I understand this is not wanted because you want to work with styles etceters. It's just an example with a simplified problem)
Now I want to make a xsl-fo block, and I want to place that attributes in the block element by using the xsl-function xsl:attribute
<fo:block>
<attribute name="{replace(#name,'_','-')}" select="#value" />
....
</fo:block>
goal to achieve after transformation
<fo:block font-size="7pt">
....
</fo:block
It doesn't function and I think this is because in xslt I can't put an hyphen in the attribute name, but in the fo-attribute it is needed.
Is there a way to use the xsl:attribute function for this?
And when not, what kind of working around do you suggest.
Thank you for helping!!!!
There are 1000 ways to do it, here is one (I didn't do anything with your Report element):
Input:
<Report>
<text content="I am a text">
<blockFormat name="font_size" value="7pt" />
</text>
</Report>
XSL:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
version="1.0">
<xsl:template match="Report">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="text">
<fo:block>
<xsl:apply-templates select="blockFormat/#*"/>
<xsl:value-of select="#content"/>
</fo:block>
</xsl:template>
<xsl:template match="#name">
<xsl:attribute name="{translate(.,'_','-')}">
<xsl:value-of select="ancestor::blockFormat/#value"/>
</xsl:attribute>
</xsl:template>
<xsl:template match="#value"/>
</xsl:stylesheet>
Output:
<Report>
<fo:block xmlns:fo="http://www.w3.org/1999/XSL/Format" font-size="7pt">I am a text</fo:block>
</Report>
Use #select instead of #value:
<fo:block>
<attribute name="{replace(#name,'_','-')}" select="#value" />
....
</fo:block>
See https://www.w3.org/TR/xslt20/#creating-attributes
Also, you need to be using XSLT 2.0 or 3.0 to use #select. If you're using XSLT 1.0, you'd have to do it as xsl:attribute/xsl:value-of/#select.
(It would also have helped understanding of your problem if you'd also shown the wrong result that you were getting.)

How can I keep my content from being cutoff with apache fop?

I am going through the Apache FOP quickstart. From the command line I am converting a simple xml file that contains an svg element and converting it to a pdf file. I am able to do this, but the image generated by the svg is being cut off. I am new to XSL-FO & Apache FOP, but I did check out the w3c documentation of properties. Now I'm even more confused, unfortunately. I have tried the following with no luck: altering the width & height properties in the svg itself; setting page-height & page-width to "auto" in the simple page master element; eliminating the margin property. I didn't see anything indicating the region-body starts with some default size.
Here is the xml:
<chart>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="600" height="100">
<circle cx="50" cy="50" r="40" stroke="black" stroke-width="2" fill="red" />
<circle cx="100" cy="100" r="40" stroke="black" stroke-width="2" fill="green" />
</svg>
And here's the xsl:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<fo:root>
<fo:layout-master-set>
<fo:simple-page-master master-name="A4-portrait"
margin="10">
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="A4-portrait">
<fo:flow flow-name="xsl-region-body">
<fo:block>
<fo:instream-foreign-object xmlns:svg="http://www.w3.org/2000/svg" content-width="600" content-height="300">
<svg:svg>
<xsl:copy-of select="/chart/svg:svg"/>
</svg:svg>
</fo:instream-foreign-object>
</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
</xsl:stylesheet>
The image is supposed to show a red & green circle overlapping, but it's only showing the upper left corner of the green one. I expect there's a property in the block element I am missing, but I don't know which. I looks like the block is limited to a 100px x 100px size.
What am I missing of the properties and how can I get the whole svg image to show properly (two full circles overlapping)?
Thanks,
Brandt
PS: I would have sent an image showing the problem, but I don't have a high enough reputation.
Errors are the specification of size with no units in FO in three places (margin, content-width and content-height). Also the SVG as stated in the comment above has a height of 100 which exceeds half of the green circle.
Correcting these and showing just the FO:
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master master-name="A4-portrait">
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="A4-portrait">
<fo:flow flow-name="xsl-region-body">
<fo:block>
<fo:instream-foreign-object xmlns:svg="http://www.w3.org/2000/svg">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="600" height="200">
<circle cx="50" cy="50" r="40" stroke="black" stroke-width="2" fill="red" />
<circle cx="100" cy="100" r="40" stroke="black" stroke-width="2" fill="green" />
</svg>
</fo:instream-foreign-object>
</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
This shows the complete SVG image in your output.