1
votes

We're using Apache FOP 1.1 with XSLT to generate a PDF for printing. Our software is creating the XML correctly, and passing this directly to the FOP transformer. We are not saving anything to file so the use of transformer properties to indent the XML is not going to help here.

Basically our XML generator creates an XML document that looks like this:

<document><list><item>1</item><item>2</item><item>3</item></list></document>

and our XSLT has a bit that takes each item child of the list node and is suppose to print them out with a space in between. Something like this:

<!DOCTYPE xsl:stylesheet [
     <!ENTITY nbsp '<xsl:text xmlns:xsl="http://www.w3.org/1999/XSL/Transform">&#160;</xsl:text>'>
]>
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes" /> 
 <xsl:template match="list">
     <fo:inline>Items:&nbsp;</fo:inline>
     <xsl:for-each select="item">
          <xsl:value-of select="./text()"/>&nbsp;
     </xsl:for-each>
</xsl:template>

At the very top of the XSLT document I've already told it what the entity &nbsp; is so that shouldn't be the problem. The problem is that when the file is generated the items instead of showing up as Items: 1 2 3 are showing up as Items: 123. The only thing I can find that seems to fix the problem is when I've generated the XML then transform it to a String where the document would now look like this:

<document>
     <list>
          <item>1</item>
          <item>2</item>
          <item>3</item>
     </list>
</document>

Does the XSLT output the list correctly. So what I would like to do is add a newline node after each item in the list via the DOM, without having to first transform it and save it to a file. Is this possible?

UPDATE! I would like to apologize to all those who helped. The correct answer was given, but since I was working on the wrong portion of the template, I wasn't seeing the correction working. Yes as you noted I didn't post the entire template, that's due to its nature and source. Some years ago I started the template and had it working, and later another developer made changes to the template and stopped using the sub-template where I was originally doing the work. So when I came back to it I was of course working where I thought it was working, and was wondering why I wasn't seeing the changes.

Thanks for the support in this. This issue is solved.

2
Are you perhaps confusing "newlines" and &#160;? This character is not a newline, it is a non-breaking space: fileformat.info/info/unicode/char/00a0/index.htm.Mathias Müller
Hi Mathias, you are right &#160; is not a newline. What I want is a space a simple space between the items. However, when the XML doesn't have a newline then the space (&#160;) is not generated.JRSofty

2 Answers

2
votes

Your entity declaration is a bit of a mess. There is a namespace declaration inside it, &#160 does not end with a semicolon.

Do not output text or even single characters without enclosing them in xsl:text elements. This ensures that they are serialized correctly. In other words, change

&nbsp;

to

<xsl:text>&nbsp;</xsl:text>

I also simplified your entity declaration. It does not make sense to include XSLT elements and a namespace declaration in an entity declaration.

You declare the XSLT namespace on xsl:stylesheet anyway and there is no need to redeclare it. xsl:text elements should be placed in actual code, not inside an entity declaration.

Input

<document><list><item>1</item><item>2</item><item>3</item></list></document>

Stylesheet

<!DOCTYPE xsl:stylesheet [
     <!ENTITY nbsp '&#160;'>
]>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format">

<xsl:strip-space elements="*"/>
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes" /> 

<xsl:template match="list">
     <fo:inline>
     <xsl:text>Items:&nbsp;</xsl:text>
     <xsl:for-each select="item">
          <xsl:value-of select="."/>
          <xsl:text>&nbsp;</xsl:text>
     </xsl:for-each>
     </fo:inline>
</xsl:template>

</xsl:stylesheet>

Output

<?xml version="1.0" encoding="utf-8"?>
<fo:inline xmlns:fo="http://www.w3.org/1999/XSL/Format">Items: 1 2 3 </fo:inline>
2
votes

Could you maybe post more of your FO Stylesheet, if I transform:

<document><list><item>1</item><item>2</item><item>3</item></list></document>

with:

<?xml version="1.0" encoding="UTF-8"?>
<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"
exclude-result-prefixes="xs"
version="1.0">

<xsl:template match="document">
    <fo:root>
        <fo:layout-master-set>
            <fo:simple-page-master master-name="test">
                <fo:region-body region-name="region"/>
            </fo:simple-page-master>
        </fo:layout-master-set>
        <fo:page-sequence master-reference="test">
            <fo:flow flow-name="region">
                <fo:block><xsl:apply-templates select="list"/></fo:block>
            </fo:flow>
        </fo:page-sequence>
    </fo:root>      
</xsl:template>

<xsl:template match="list">
    <fo:inline>Items:<xsl:text> </xsl:text></fo:inline>
    <xsl:for-each select="item">
        <xsl:value-of select="./text()"/><xsl:text> </xsl:text>
    </xsl:for-each>
</xsl:template>
</xsl:stylesheet>

I get a PDF that looks like this:

result pdf