I'm struggling with my xsl:fo (Apache Fop 1.1). I'm trying to generate a Block with inline images and inline text elements which might contain newline characters.
<fo:block>
<fo:inline>First Line Second Line, Image: </fo:inline>
<fo:inline>
<fo:external-graphic scaling="non-uniform" content-height="scale-to-fit" content-width="4mm" height="4mm" src="data:image;base64,iVBORw0KGgoAAAANSUhEUgAAAGcAAABfCAIAAAB6Ck5uAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAA0SURBVHhe7cGBAAAAAMOg+VNf4QBVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHCoAXMKAAFau+l4AAAAAElFTkSuQmCC"/>
</fo:inline>
<fo:inline> some more Text on Line 2 3rd Line</fo:inline>
</fo:block>
I expect the output would be
FirstLine
SecondLine, Image: || some more Text on Line 2
3rd Line
what I get is:
FirstLine SecondLine, Image: || some more Text on Line 2 3rd Line
I've been playing a while now with the following attributes on the fo:block element and/or the fo:inline elements giving strange or unexpected results.
white-space-collapse="false"
white-space-treatment="preserve"
linefeed-treatment="preserve"
Any suggestions?
Edit 1: Changing the inline elements into blocks like this
<fo:block white-space-treatment="ignore">
<fo:block white-space="pre">First Line
Second Line, Image: </fo:block>
<fo:block>
<fo:external-graphic scaling="non-uniform" content-height="scale-to-fit" content-width="4mm" height="4mm" src="data:image;base64,iVBORw0KGgoAAAANSUhEUgAAAGcAAABfCAIAAAB6Ck5uAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAA0SURBVHhe7cGBAAAAAMOg+VNf4QBVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHCoAXMKAAFau+l4AAAAAElFTkSuQmCC"/>
</fo:block>
<fo:block white-space="pre"> some more Text on Line 2 3rd Line</fo:block>
</fo:block>
gives me the expected wrapping within the elements, but a new line is generated for each block which isn't what I'm trying to archive.
Linefeeds can be present in an FO document as linefeed characters or numeric character entities (

or
); the following FO blocks are completely equivalent:
<fo:block>Before the linefeed
after the linefeed.</fo:block>
<fo:block>Before the linefeed
after the linefeed.</fo:block>
The default handling of linefeeds consists in:
This explains why your initial input produces an output where all the content pieces are placed consecutively on the same line.
Using the property linefeed-treatment="preserve"
both forms of linefeeds are retained, and the line building process will respect them (they are called forced line-breaks). Note that linefeed-treatment
only applies to fo:block
elements; it has no effect on fo:inline
elements.
Your "edit 1" block has more linefeeds than you need because "... Second Line, Image: ", the image and "some more Text on Line 2 ..." are inside three different fo:block
elements, and each block generates its own lines.
The simplest way to get your desired output is probably this one, with a single fo:block
having its linefeed preserved (this is just your original input, after removing the unnecessary fo:inline
s and putting everything on the same line:
<fo:block linefeed-treatment="preserve">First Line
Second Line, Image: <fo:external-graphic scaling="non-uniform" content-height="scale-to-fit" content-width="4mm" height="4mm" src="data:image;base64,iVBORw0KGgoAAAANSUhEUgAAAGcAAABfCAIAAAB6Ck5uAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAA0SURBVHhe7cGBAAAAAMOg+VNf4QBVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHCoAXMKAAFau+l4AAAAAElFTkSuQmCC"/> some more Text on Line 2 3rd Line</fo:block>
Note that you cannot indent this code, because the extra linefeeds would appear in the output too!
A second solution, which doesn't involve using the linefeed-treatment
property and creates more easily readable code, would be to use empty blocks instead of forced linefeeds:
<fo:block>
First Line<fo:block/>Second Line, Image:
<fo:external-graphic scaling="non-uniform" content-height="scale-to-fit" content-width="4mm" height="4mm" src="data:image;base64,iVBORw0KGgoAAAANSUhEUgAAAGcAAABfCAIAAAB6Ck5uAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAA0SURBVHhe7cGBAAAAAMOg+VNf4QBVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHCoAXMKAAFau+l4AAAAAElFTkSuQmCC"/>
some more Text on Line 2<fo:block/>3rd Line
</fo:block>
As linefeeds are not preserved, we can use them freely:
<fo:block>
First Line
<fo:block/>
Second Line, Image:
<fo:external-graphic scaling="non-uniform" content-height="scale-to-fit" content-width="4mm" height="4mm" src="data:image;base64,iVBORw0KGgoAAAANSUhEUgAAAGcAAABfCAIAAAB6Ck5uAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAA0SURBVHhe7cGBAAAAAMOg+VNf4QBVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHCoAXMKAAFau+l4AAAAAElFTkSuQmCC"/>
some more Text on Line 2
<fo:block/>
3rd Line
</fo:block>
The empty blocks partition the content of the outer block without creating anything in the output.
Just found the answer in the comments of FOP 1536.
Now I'm using
linefeed-treatment="preserve"
on the block element and I'm replacing all spaces within the text inlines with some unicode magic in the xsl before:
replace(@text, ' ', ' ​')
Edit 1: To be a bit more precise, this is the relevant part of the xsl I'm using:
<!DOCTYPE xsl:stylesheet [
<!ENTITY nbsp " ">
<!ENTITY ZeroWidthSpace "​">
]>
<fo:block linefeed-treatment="preserve">
<fo:inline><xsl:value-of select="replace(@text, ' ', ' ​')"/></fo:inline>
</fo:block>
With this approach I'm getting a pretty clean indented xml while having full control over linebreaks and blank spaces.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With