[英]PDF report with embedded HTML
我們有一個基於Java的系統,該系統從數據庫讀取數據,將單個數據字段與預設的XSL-FO
標簽合並,然后使用Apache FOP
將結果轉換為PDF
。
在XSL-FO
格式中,它看起來像這樣:
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE Html [
<!ENTITY nbsp " ">
<!-- all other entities -->
]>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:output method="xml" indent="yes" />
<xsl:template match="/">
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:svg="http://www.w3.org/2000/svg" font-family="..." font-size="...">
<fo:layout-master-set>
<fo:simple-page-master master-name="Letter Page" page-width="8.500in" page-height="11.000in">
<!-- appropriate settings -->
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="Letter Page">
<!-- some static content -->
<fo:flow flow-name="xsl-region-body">
<fo:block>
<fo:table ...>
<fo:table-column ... />
<fo:table-body>
<fo:table-row>
<fo:table-cell ...>
<fo:block text-align="...">
<fo:inline font-size="..." font-weight="...">
<!-- Header / Title -->
</fo:inline>
</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
</fo:block>
<fo:block>
<fo:table ...>
<fo:table-column ... />
<fo:table-body>
<fo:table-row>
<fo:table-cell>
<fo:block ...>
<!-- Field A -->
</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
<!-- Other fields in a very similar fashion as the above "Field A" -->
</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
</xsl:stylesheet>
現在,我正在尋找一種允許某些字段包含靜態HTML格式內容的方法。 此內容將由我們啟用HTML的編輯器(類似於CLEditor
, CKEditor
等)生成,或者從外部粘貼。
我的計划是遵循此JavaWorld文章的配方:
JTidy
將HTML格式的字符串轉換為正確的XHTML 我有這樣的代碼的准系統版本,並收到以下錯誤:
(錯誤位置未知)org.apache.fop1.fo.ValidationException:“ { http://www.w3.org/1999/XSL/Format } table-body”不是“ fo:block”的有效子代! (沒有可用的上下文信息)
我的問題:
<fo:block>
可以用作嵌套了其他對象(包括表)的通用容器嗎? 如果有人已經“ 在那里做過 ”,請分享您的經驗。
如果在oXygen或XML Spy中使用XSLT調試器,則可以逐步完成轉換。 使用oXygen(不確定XML Spy或其他編輯器)時,如果單擊調試器輸出中的標記,則oXygen將從源和生成該節點的樣式表中突出顯示標記。
擁有FO后, focheck框架( https://github.com/AntennaHouse/focheck )具有當前可用的最完整的FO驗證。
fo:block
可以包含表等。在XSL 1.1規范中,每個FO的定義都包括一個“ Contents”小節,列出了其允許的內容。 參見例如http://www.w3.org/TR/xsl11/#fo_block 。 內容模型中“參數實體”的定義位於http://www.w3.org/TR/xsl11/#d0e6532 ,但是某些FO在其定義文本中有其他限制。 可以將<!-- Field A -->
替換為非FO標記,以提供足夠的信息來引用要插入的字段,而不是將從JTidy-ed HTML轉換的FO插入到靜態FO中。 然后,您可以制作XSLT樣式表,方法是對FO部分進行身份轉換(如@ kevin-brown的回答),並使用引用標記中的信息來構造模板,從而將模板+引用文檔轉換為純FO。與document()
函數( http://www.w3.org/TR/xslt#document )一起使用的URI,以查找要插入的標記。
如果字段內容的FO位於磁盤上,則使用document()
很簡單。 如果不是,那么您就必須執行諸如覆蓋XSLT處理器所使用的URIResolver之類的操作,以便與其在磁盤上查看,不如在磁盤上進行檢索內容。 您甚至可以在檢索HTML的URIResolver中使JTidying發生。 您也可以在URIResolver內部進行到FO的轉換,也可以按照@ kevin-brown的建議,將其轉換為單獨的模式。 如果轉換是在URIResolver檢索FO之前或期間完成的,則對FO的模板+引用的“主”轉換只需要提取FO子文檔的正確部分,例如document('constructed-URI')/fo:root/fo:page-sequence/*
。 但是,如果您要從Antenna House修改樣式表,則應該能夠對其進行修改,以使其始終不產生外部fo:root
等。
幾年前,我做了一些類似的事情,為基於XSLT的服務器重寫libxslt XSLT處理器的URI解析器:內部XSLT處理器連續運行的上下文被另存為特殊URI的文檔,而不必寫入文件系統完全沒有
相反,您可以編寫擴展功能來查找對字段的引用。 例如,W3C的Print and Page Layout Community Group @已為多個XSLT處理器生成了擴展功能,這些擴展功能在XSLT轉換的中間運行FO處理器,以獲取格式化結果的區域樹的XML。 參見http://www.w3.org/community/ppl/wiki/XSLTExtensions
解決問題的最佳方法是使用驗證查看器/編輯器檢查XSL FO。 當您打開它們時,許多(例如oXygen)將向您顯示XSL FO結構中的錯誤,並且它們將描述問題(就像報告的錯誤一樣)。
在您的情況下,您顯然有一個fo:table-body作為fo:block的子級。 它不可能是。 一個fo:table-body只有一個有效的父對象fo:table。 您或者缺少fo:table標記,或者在該位置錯誤地插入了fo:block。
在我看來,我做的事情可能略有不同。 我會將XHTML內容內聯到XSL FO中,就在您需要的位置。 然后,我將創建一個標識轉換,復制所有基於fo的內容,但使用XSL轉換XHTML部分。 這樣,您實際上可以在像oXygen這樣的XSL編輯器中逐步進行轉換,並查看錯誤發生的位置以及原因。 像其他任何騙子一樣。
注意:您可能還希望查看其他XSL,尤其是在HTML可能具有任何style =“” CSS屬性的情況下。 如果是這種情況,那么它不是簡單的HTML,那么您將需要一個更好的方法來將CSS與FO一起處理HTML。
http://www.cloudformatter.com/css2pdf基於此完整的轉換。 該常規樣式表可在此處獲得: http : //xep.cloudformatter.com/doc/XSL/xeponline-fo-translate-2.xsl
我是該樣式表的作者。 它的功能遠遠超出您的要求,但是具有相當復雜的解析遞歸,可以將CSS樣式轉換為XSL FO屬性。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.