XSLT new lines not being preserved - pdf

For some reason my spaces aren't being preserved in my final PDF after xslt. My desired output is:
Static
text bold.
Here's my xslt template:
<xsl:preserve-space elements="*" />
<xsl:strip-space elements="" />
<xsl:template match="coverPage">
<fo:block font-size="12pt" color="black" text-align="center">
<xsl:text>
Static
text
</xsl:text>
</fo:block>
<fo:block font-size="12pt" color="black" text-align="center" font-weight="bold">
<xsl:text>
bold.
</xsl:text>
</fo:block>
</xsl:template>

I think there are a few issues with your XSLT:
there is no need to enclose the text inside xsl:text elements, as those text nodes are not composed only of whitespace characters and therefore will never be stripped (see Whitespace stripping for more details)
for the same reason, there is no need to use xsl:preserve-space and xsl:strip-space, unless of course you need them for other reasons
preserving linefeeds in the transformation from XML to XSL-FO is just the (required) first step, but then you must preserve them during the processing of the XSL-FO file; in order to do this, you must use the linefeed-treatment property: linefeed-treatment="preserve"
a literal linefeed is equivalent to a
entity, so in your input you have 3 linefeeds between "Static" and "text", which will produce two empty lines when preserved; if that's not what you want, you have to remove some of them
the words "text" and "bold" are inside two different fo:block elements, so this means they will always be on different lines; if you want them to be placed one beside the other, those words must be inside fo:inline elements instead (and there must be an outer fo:block to contain them)
A final word of warning
While looking at an FO file the difference between a preserved linefeed and an ignored one is not immediately apparent, as it boils down to the presence of the linefeed-treatment attribute in an ancestor element (which could be quite far from the text node itself).
Clearer ways to force a line break in a specific position include:
using different fo:block elements, each one containing the text that should create a line (or several ones)
<fo:block>Static</fo:block>
<fo:block>text <fo:inline font-weight="bold">bold.</fo:inline></fo:block>
using an empty fo:block where a line break should be
<fo:block>
Static
<fo:block/>
text <fo:inline font-weight="bold">bold.</fo:inline>
</fo:block>

Related

How to align paragraph in XSl FO PDF

I want to align a paragraph below in XSL fO.
Label : value
Be careful not to set the heap size too large, as whatever
you allocate reduces the amount of memory available to the
operating system and other programs, which could cause
excessive paging (memory swapped back and forth between
RAM and the swap disc, which will slow your system down)
with proper alignment and indentation. Am able to create with word-breaks but indentation is missing .can anyone suggest the solution
Think you something like this?
<fo:block text-align="justify" margin-left="1.5cm">Your text here ...</fo:block>
Or you can use linefeed-treatment white-space-treatment, whitespace-collapse attributes together for preformatted texts.
And you can drop the fo:block into a fo:block-container for background coloring and bordering.
<fo:block margin-left="5mm" margin-right="5mm"
font-family="verdana" font-size="12pt"
space-before="5mm" space-after="5mm" keep-together="always"
linefeed-treatment="preserve" whitespace-treatment="pre" whitespace-collapse="false">
Your multiline
code here,
and more lines,
with multiple spaces on start and within
and empty lines ...
</fo:block>

How to add dynamic text on the tooltip text in XSLT

How do we add dynamic tooltip text in xslt
<axf:form-field field-type="button" field-name="tooltip1" field-description="fileName" width="160mm" height="5mm"
background-color="#ffffff" field-button-face-down="​">
</axf:form-field>
In the above tag field-description is considering the filename as a constant but I want it to read value of filename coming from
<xsl:variable name="fileName" select="string(../comment()[2])"/>
I tried field-description="$fileName" but its taking whole thing as constant i.e $fileName

XSLT: variables and "empty" labels

I have an XML datafile containing among other things a string of arbitrarily many comma separated values. I want those values to be displayed in a web browser as a list with one value per line. So I wrote an XSLT template that takes this string, displays the first value followed by a linebreak tag (<br/>), properly name-spaced, and resources with the remainder of the string. In effect, the commas are being replaced by HTML <br/> tags.
Now, when I store the result of calling that template in a xsl:variable, and display that through xsl:value-of, then the HTML tags disappear: what is shown is the string minus the commas.
When I display the result directly by having the xsl:call-template in place of the xsl:value-of, all is fine, and the values appear in a list.
So, what's going on?
Is this behavior an implementation artifact, or is it standard XSLT?
Use xsl:copy-of instead of xsl:value-of if you want to output nodes (like your br elements), xsl:value-of creates a simple text node with the string value(s) selected.
Here is an example that shows the difference between xsl:value-of and xsl:copy-of, you will note that it is not the use of the variable with newly created br elements that makes the difference, it is simply the use of xsl:value-of that creates a text() node with the string conversion of the selection:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="html" indent="yes" version="5" doctype-system="about:legacy-doctype"/>
<xsl:variable name="var">Phrase 1.<br/>Phrase 2.<br/>Phrase 3.</xsl:variable>
<xsl:template match="/">
<html>
<head>
<title>.NET XSLT Fiddle Example</title>
</head>
<body>
<section>
<h1>Example 1: value-of</h1>
<xsl:value-of select="$var"/>
</section>
<section>
<h1>Example 2: copy-of</h1>
<xsl:copy-of select="$var"/>
</section>
<xsl:apply-templates select="//p"/>
<xsl:apply-templates select="//p" mode="copy-of"/>
</body>
</html>
</xsl:template>
<xsl:template match="p">
<section>
<h1>Example 1: value-of</h1>
<xsl:value-of select="."/>
</section>
</xsl:template>
<xsl:template match="p" mode="copy-of">
<section>
<h1>Example 1: copy-of</h1>
<xsl:copy-of select="."/>
</section>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/gWmuiJy/1
Output is
Example 1: value-of
Phrase 1.Phrase 2.Phrase 3.
Example 2: copy-of
Phrase 1.
Phrase 2.
Phrase 3.
Example 1: value-of
Line 1.Line 2.Line 3.
Example 1: copy-of
Line 1.
Line 2.
Line 3.
It seems that you hit the boundaries of the RTF ("Result tree fragment"):
When you use an XML fragment to initialize a variable or a parameter, then the variable or parameter is of the
"result tree fragment" datatype. This is an XSLT 1.0 specific datatype [just like node-set, but slightly different].
A result tree fragment is equivalent to a node-set that contains just the root node.
You cannot apply operators like "/", "//" or predicate on a result tree fragments. They are only applicable for node-set datatypes.
[...]
a) In XSLT 1.0
The resolution of this is to convert the result tree fragment into a node-set. I am not aware of any oracle specific xpath extension functions that can do this trick for you.
You could use EXSLT to achieve this.
b) Use XSLT 2.0
You can code your transformations in XSLT 2.0. XSLT 2.0 deprecates ResultTreeFragments i.e. if you are modeling an XSLT 2.0 transformation, and you create a variable or a parameter that holds a tree fragment, it is implicitly a node sequence.
So without using an XSLT version greater than 1, you're out of luck. So better use XSLT-2.0 or 3.0 to solve this problem.
Is this behavior an implementation artifact, or is it standard XSLT?
It is standard for XSLT-1.0, but not for XSLT-2.0+.

escaping an ampersand in xsl variable

I'm trying to encode certain text variables into a QR code using qrserver.com. (specifically, a gift message on a packing slip)
Here's the snippet of code relevant to the encoding:
<!-- gift message -->
<xsl:for-each select="Customer/Order/Item">
<xsl:for-each select="Option[Name='Gift Message (optional)']">
<xsl:variable name="test" select="translate(Description,'','')" />
<xsl:value-of select="concat('https://api.qrserver.com/v1/create-qr-code/?data=', $test,'&size=100x100&charset-source=UTF-8')" />
</xsl:for-each>
</xsl:for-each>
Occasionally the text will contain an ampersand, like "Merry Christmas & Happy New Year", so the url that is passed is
https://api.qrserver.c-o-m/v1/create-qr-code/?data=Merry Christmas & Happy New Year&size=100x100
and everything after the ampersand gets truncated. The result is a QR code that encodes "Merry Christmas" but no Happy New Year. I tried using the translate function to replace the ampersand with "and", but translate(Description,'&','and') only works on the first letter, so it replaces the ampersand with "a". This is in xsl 1.0, so I don't have the option of the replace function. Does anyone out there know how I can deal with these ampersands? Thanks in advance!

XSL: chop off string at arbitrary place

I'm using XSL to get an XML styled. The xsl defines a table with two columns. Thanks to Kevin Brown, the following code works fine to chop off at a word boundary, but what I need is to chop off at an arbitrary place.
<fo:table-cell>
<fo:block-container overflow="hidden" height="15pt"><fo:block>this is a very, very, very long text here</fo:block></fo:block-container>
</fo:table-cell>
If you generate this from XML and XSL, you would normally create a template when outputting that particular content and place ​ entities (the zero-width breaking space character). So however you do it, make the content like this (this says "very long word" with that entity between the letters:
v​e​r​y l​o​n​g w​o​r​d
So in your example (I only put them near the break so you can see):
<fo:table-cell border="1pt solid silver">
<fo:block-container overflow="hidden" height="15pt"><fo:block>this is a very, very, very l​o​n​g t​e​x​t here</fo:block></fo:block-container>
</fo:table-cell>
You would get this now ( it breaks at "o" in "long"):
A very interesting effect if you are so inclined is to set "text-align" as "justify" on that fo:block which will actually make all things align if at the end of the block you inserted an fo:leader of sufficient length to fill the cell. NOTE: This does not work in Apache FOP, it does in RenderX XEP.
Like:
<fo:table-cell border="1pt solid silver">
<fo:block-container overflow="hidden" height="15pt"><fo:block text-align="justify">this is a<fo:leader leader-length.minimum="3in"/></fo:block></fo:block-container>
</fo:table-cell>
If you did that, you would get this: