2014-05-05 59 views
0

的我這是違背XML內容和XSL標記Apache防和給我的apache的中間格式輸出代碼:FOP渲染成PDF的一頁了許多

StreamSource contentSource = new StreamSource(xmlContentStream); 
StreamSource transformSource = new StreamSource(xslMarkupStream); 

ByteArrayOutputStream outStream = new ByteArrayOutputStream(); 
Transformer xslfoTransformer = getTransformer(transformSource); 

FOUserAgent foUserAgent = fopFactory.newFOUserAgent(); 
IFDocumentHandler targetHandler = foUserAgent.getRendererFactory().createDocumentHandler(
       foUserAgent, MimeConstants.MIME_PDF); 

FPSIFSerializer fpsSerializer = new FPSIFSerializer(); 

fpsSerializer.setContext(new IFContext(foUserAgent)); 
fpsSerializer.mimicDocumentHandler(targetHandler); 
foUserAgent.setDocumentHandlerOverride(fpsSerializer); 

Fop fop = fopFactory.newFop("application/X-fop-intermediate-format", foUserAgent, outStream); 

DefaultHandler defaultHandler = fop.getDefaultHandler(); 

Result res = new SAXResult(defaultHandler); 
xslfoTransformer.transform(contentSource, res); 

然後我用的中間格式文件渲染pdf和PNG文件。 我可以在這裏設置我自己的序列化器(FPSIFSerializer())。

我有幾頁報告,但我不需要處理所有這些報告。有沒有辦法跳過一些頁面或從IntermediateFormat中提取它們,這樣我就可以只呈現第一頁爲PNG,然後第二至PDF等? There http://svn.apache.org/viewvc/xmlgraphics/fop/branches/archive/fop-1_1/examples/embedding/java/embedding/intermediate/ExampleConcat.java?view=markup 是如何通過IFConcatenator連接文件的示例,所以我想知道分割多頁文件的最佳方法嗎?

Thank_you!

回答

0

我這樣做的方式是使用自定義文檔處理程序。

/** 
* Custom Apache FOP Intermediate Format document handler which allows page skipping. 
* Not thread safe. 
*/ 
public class IFPageFilter extends IFDocumentHandlerProxy { 
private static final Logger LOGGER = LoggerFactory.getLogger(IFPageFilter.class); 
private int currentPage; 
private final int desiredPage; 

/** 
* @param delegate The real document handler 
* @param desiredPage the page you want to render (1-based). Other pages will be skipped. 
*/ 
public IFPageFilter(final IFDocumentHandler delegate, final int desiredPage) { 
    super(delegate); 
    this.desiredPage = desiredPage; 
} 


@Override 
public void startPage(final int index, final String name, final String pageMasterName, final Dimension size) throws IFException { 
    currentPage = index + 1; 
    if (currentPage == desiredPage) { 
     super.startPage(index, name, pageMasterName, size); 
    } else { 
     // do nothing 
      LOGGER.debug("Page skipped"); 
    } 
} 

@Override 
public IFPainter startPageContent() throws IFException { 
    if (currentPage == desiredPage) { 
     return super.startPageContent(); 
    } else { 
     return EmptyPainter.getInstance(); 
    } 
} 

@Override 
public void endPageContent() throws IFException { 
    if (currentPage == desiredPage) { 
     super.endPageContent(); 
    } 
    } 
} 

然後你可以將你的處理器這樣的:

final IFDocumentHandler targetHandler = FOP_FACTORY.getRendererFactory().createDocumentHandler(userAgent, mime); 
    final IFPageFilter documentHandler = new IFPageFilter(targetHandler, page); 
final ByteArrayOutputStream mimeOut = new ByteArrayOutputStream(XSL_STREAM_BUFFER_SIZE); 

    IFUtil.setupFonts(documentHandler); 

    // Tell the target handler where to write the PDF to 
    targetHandler.setResult(new StreamResult(mimeOut)); 
    try (final InputStream is = ifStream.toInputStream()) { 
     final Source src = new StreamSource(is); 
     new IFParser().parse(src, documentHandler, userAgent); 
    } 
    return mimeOut; 

,你會得到你的輸出流中唯一需要的頁面。 Class EmptyPainter是一個骯髒的黑客。它是apache IFPainter的空實現,它在這裏用來跳過頁面內容並避免NPE。我對此並不滿意,但這是我能夠使其工作的唯一途徑。

請注意,我使用FOP 1.1,如果你遇到這樣的問題,那麼值得看一看樹幹 - 其中一些已經在那裏解決了。我認爲EmptyPainter的骯髒破解在trunk中不是必需的。

如果在這裏可以做得更好,請給出提示。

謝謝