How to add newline after an xml node so that FOP will recognize whitespace?

家住魔仙堡 提交于 2019-12-11 06:56:32

问题


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.


回答1:


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:


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:



来源:https://stackoverflow.com/questions/22013570/how-to-add-newline-after-an-xml-node-so-that-fop-will-recognize-whitespace

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!