Xsl: fo line line wrap and line break

I am struggling with my xsl: fo (Apache Fop 1.1). I am trying to create a block with inline images and inline text elements that may contain newline characters.

<fo:block> <fo:inline>First Line&#10;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&#10;3rd Line</fo:inline> </fo:block> 

I expect the result to be

 FirstLine SecondLine, Image: || some more Text on Line 2 3rd Line 

what i get:

 FirstLine SecondLine, Image: || some more Text on Line 2 3rd Line 

I played now with the following attributes in the fo: block element and / or in the fo: inline elements giving strange or unexpected results.

 white-space-collapse="false" white-space-treatment="preserve" linefeed-treatment="preserve" 

Any suggestions?

Edit 1: Change inline elements in blocks like this

 <fo:block white-space-treatment="ignore"> <fo:block white-space="pre">First Line&#xA;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&#10;3rd Line</fo:block> </fo:block> "non-uniform" content-height = "scale-to-fit" content-width = "4mm" height = "4mm" src = "data: image; base64, iVBORw0KGgoAAAANSUhEUgAAAGcAAABfCAIAAAB6Ck5uAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAA0SURBVHhe7cGBAAAAAMOg + VNf4QBVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHCoAXMKAAFau + l4AAAAAElFTkSuQmCC <fo:block white-space-treatment="ignore"> <fo:block white-space="pre">First Line&#xA;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&#10;3rd Line</fo:block> </fo:block> 

gives me the expected wrapper inside the elements, but a new line is created for each block, which is not what I'm trying to archive.

+5
source share
2 answers

Line feeds may appear in the FO document as line feeds or numeric characters ( &#x000A; or &#10; ); The following FO blocks are fully equivalent:

 <fo:block>Before the linefeed&#x000A;after the linefeed.</fo:block> <fo:block>Before the linefeed after the linefeed.</fo:block> 

The default string processing consists of:

  • transforming them into normal spaces;
  • collapses them with other neighboring spaces.

This explains why your original input produces output where all parts of the content are placed sequentially on the same line.

Using the linefeed-treatment="preserve" property, both line shapes are saved, and the line : fo: block line building process and each block generates its own lines.

Solution 1:

The easiest way to get the desired result is, perhaps, one of them: one fo:block with saving the line (this is only your original input, after deleting the unnecessary fo:inline and placing it in only one line:

 <fo:block linefeed-treatment="preserve">First Line&#xA;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&#10;3rd Line</fo:block> 

Please note that you cannot backtrack from this code because additional output lines will also appear on the output!

Solution 2:

The second solution, which is not related to using the linefeed-treatment property and creates more readable code, would be to use empty blocks instead of forced lines:

 <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> "non-uniform" content-height = "scale-to-fit" content-width = "4mm" height = "4mm" src = "data: image; base64, iVBORw0KGgoAAAANSUhEUgAAAGcAAABfCAIAAAB6Ck5uAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAA0SURBVHhe7cGBAAAAAMOg + VNf4QBVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHCoAXMKAAFau + l4AAAAAElFTkSuQmCC <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> 

Since line feeds are not saved, 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> "non-uniform" content-height = "scale-to-fit" content-width = "4mm" height = "4mm" src = "data: image; base64, iVBORw0KGgoAAAANSUhEUgAAAGcAAABfCAIAAAB6Ck5uAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAA0SURBVHhe7cGBAAAAAMOg + VNf4QBVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHCoAXMKAAFau + l4AAAAAElFTkSuQmCC <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> 

Empty blocks divide the contents of the outer block without creating anything in the output.

+9
source

Just found the answer in the comments of FOP 1536 .

Now i use

 linefeed-treatment="preserve" 

on a block element, and I replace all spaces inside text strings with some unicode masks in xsl to:

 replace(@text, ' ', '&#x00A0;&#x200B;') 

Edit 1: To be more precise, this is the important part of xsl that I use:

 <!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp "&#160;"> <!ENTITY ZeroWidthSpace "&#x200B;"> ]> <fo:block linefeed-treatment="preserve"> <fo:inline><xsl:value-of select="replace(@text, ' ', '&nbsp;&ZeroWidthSpace;')"/></fo:inline> </fo:block> 

With this approach, I get pretty clean xml indentation, with full control over line breaks and spaces.

+1
source

Source: https://habr.com/ru/post/1215582/


All Articles