xml轉PDF(xml&xslt->fo->pdf)_完整項目_CodingPark編程公園

文章介紹

1 製作一個xml實例
2 製作一個XSLT(fo)式樣單
3 將XML文檔通過XSLT轉換成XSL-FO
4 採用FOP將上述文檔轉換成PDF格式
5 總結與思考

預備知識語法庫

xml 與 xsl(fo)
<?xml version="1.0" encoding="UTF-8"?>
<!--如果xml+xslt(fo)可以不寫  |	 如果xml+xsl可以寫,當你oxygen運行時它會幫你調瀏覽器-->
<?xml-stylesheet type="text/xsl" href="Sample.xsl" ?> 
<ItemListReport>
	<ReportHeader>
		<Title>明確條款</Title>
		<PartyA>TEAM-AG</PartyA>
		<PartyB>編程公園技術有限公司</PartyB>
	</ReportHeader>
	<ReportBody>
		<Table>
			<TableRow>
				<ItemName>附加條款</ItemName>
				<ItemTime>2022-5-12 09:03</ItemTime>
			</TableRow>
			<TableRow>
				<ItemName>編程公園技術有限公司(bj)</ItemName>
				<ItemTime>2022-12-23 09:03</ItemTime>
			</TableRow>
			<TableRow>
				<ItemName>編程公園技術有限公司(cd)</ItemName>
				<ItemTime>2023-2-23 09:03</ItemTime>
			</TableRow>
			<TableRow>
				<ItemName>編程公園技術有限公司(sh)</ItemName>
				<ItemTime>2025-11-3 09:03</ItemTime>
			</TableRow>
			<TableRow>
				<ItemName>編程公園技術有限公司(sz)</ItemName>
				<ItemTime>2026-2-23 09:03</ItemTime>
			</TableRow>
		</Table>
	</ReportBody>
	<ReportFooter>
		<PrintDate>2032-5-1</PrintDate>
		<ReportNo>010-68273773</ReportNo>
	</ReportFooter>
</ItemListReport>
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
	xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
	xmlns:fo="http://www.w3.org/1999/XSL/Format" exclude-result-prefixes="fo">

	<!-- 根元素  -->
	<xsl:template match="/">
		<xsl:apply-templates select="ItemListReport" />
	</xsl:template>

	<!--主模板//-->
	<xsl:template match="ItemListReport">
		<xsl:processing-instruction name="cocoon-format">type="text/xslfo"</xsl:processing-instruction>
		<!--在此可以定義一些全局的風格信息,如字體等-->
		<fo:root font-family="SimSun" xmlns:fo="http://www.w3.org/1999/XSL/Format">
			<!--版面定義//-->
			<fo:layout-master-set>
				<fo:simple-page-master master-name="main" margin-top="1cm" margin-bottom="1cm" margin-left="1cm" margin-right="1cm">
					<!--主體//-->
					<fo:region-body margin-top="1cm" margin-bottom="1cm" />
					<!--頁眉//-->
					<fo:region-before extent="1cm" />
					<!--頁腳//-->
					<fo:region-after extent="1cm" />
				</fo:simple-page-master>
			</fo:layout-master-set>

			<fo:page-sequence master-reference="main">
				<!--頁眉顯示內容-->
				<fo:static-content flow-name="xsl-region-before">
					<fo:block font-size="10pt" text-align="end" line-height="12pt">PDF 報表樣例</fo:block>
					<!-- <fo:block text-align="end">
						<fo:external-graphic src="report/sample/title.jpg"/>
				    </fo:block> -->
				</fo:static-content>
				<!--頁腳顯示內容-->
				<fo:static-content flow-name="xsl-region-after">
					<fo:block line-height="10pt" font-size="10pt" text-align="center"><fo:page-number-citation ref-id="endofdoc"/><xsl:text>       </xsl:text><fo:page-number/></fo:block>
				</fo:static-content>
				<!--頁面主體內容-->
				<fo:flow flow-name="xsl-region-body">
					<!--報表頭-->
					<xsl:apply-templates select="ReportHeader" />
					<!--報表體(若有多個部分內容,參照下面一行重複)-->
					<xsl:apply-templates select="ReportBody" />
					<!--報表尾-->
					<xsl:apply-templates select="ReportFooter" />
				</fo:flow>
			</fo:page-sequence>
		</fo:root>
	</xsl:template>

	<!--報表頭//-->
	<xsl:template match="ReportHeader">
		<!--標題-->
		<fo:block font-size="24pt" font-weight="bold" line-height="30pt" vertical-align="top"
			text-align-last="center" space-before.optimum="12pt">
			<xsl:value-of select="Title" />
		</fo:block>
		<!--用一個表格來格式化顯示其餘信息-->
		<fo:block font-size="12pt">
			<fo:table table-layout="fixed" width="100%" border-collapse="separate">
				<fo:table-column column-width="1.3cm" />
				<fo:table-column column-width="17.7cm" />
				<fo:table-body>
					<fo:table-row>
						<fo:table-cell text-align="start">
							<fo:block><xsl:text>甲方:</xsl:text></fo:block>
						</fo:table-cell>
						<fo:table-cell text-align="start">
							<fo:block><xsl:value-of select="PartyA" /></fo:block>
						</fo:table-cell>
					</fo:table-row>
					<fo:table-row>
						<fo:table-cell text-align="start">
							<fo:block><xsl:text>乙方:</xsl:text></fo:block>
						</fo:table-cell>
						<fo:table-cell text-align="start">
							<fo:block><xsl:value-of select="PartyB" /></fo:block>
						</fo:table-cell>
					</fo:table-row>
				</fo:table-body>
			</fo:table>
		</fo:block>
	</xsl:template>

	<!--報表主體(一般只有一個表格)//-->
	<xsl:template match="ReportBody">
		<xsl:apply-templates select="Table" />
	</xsl:template>

	<!--報表尾//-->
	<xsl:template match="ReportFooter">
		<fo:block font-size="12pt" line-height="15pt" text-align="start" space-before.optimum="12pt">
			<xsl:text>簽訂時間:</xsl:text>
			<xsl:value-of select="PrintDate" />
		</fo:block>
		<fo:block id="endofdoc"></fo:block>
		<fo:block font-family="Code39Seven" font-size="14pt" line-height="18pt">*<xsl:value-of select="ReportNo" />*</fo:block>
	</xsl:template>

	<!--表格數據//-->
	<xsl:template match="Table">
		<fo:block font-size="12pt">
			<fo:table table-layout="fixed" width="100%" border-collapse="separate"
				text-align="center" border-width="0.5pt" border-style="solid" space-before.optimum="12pt">
				<!-- 定義列(與實際列數嚴格一致) //-->
				<fo:table-column column-width="13cm" />
				<fo:table-column column-width="6cm" />
				<!-- 定義表頭 //-->
				<fo:table-header>
					<fo:table-row font-weight="bold" font-size="13pt" border-width="0.5pt" border-style="solid">
						<fo:table-cell border-color="black" border-width="0.2pt" border-style="solid">
							<fo:block>條款名稱</fo:block>
						</fo:table-cell>
						<fo:table-cell border-color="black" border-width="0.2pt" border-style="solid">
							<fo:block>錄入時間</fo:block>
						</fo:table-cell>
					</fo:table-row>
				</fo:table-header>
				<!-- 表格數據 //-->
				<fo:table-body>
					<xsl:apply-templates select="TableRow" />
				</fo:table-body>
			</fo:table>
		</fo:block>
		<fo:block space-before.optimum="12pt">注:顯示錶格每一行的模板</fo:block>
	</xsl:template>

	<!--顯示錶格每一行的模板//-->
	<xsl:template match="TableRow">
		<fo:table-row space-before.optimum="3pt">
			<fo:table-cell border-color="black" border-width="0.2pt" border-style="solid">
				<fo:block><xsl:value-of select="ItemName" /></fo:block>
			</fo:table-cell>
			<fo:table-cell border-color="black" border-width="0.2pt" border-style="solid">
				<fo:block><xsl:value-of select="ItemTime" /></fo:block>
			</fo:table-cell>
		</fo:table-row>
	</xsl:template>
</xsl:stylesheet>
xml 與 xsl[知識擴展]
<?xml version="1.0" encoding="UTF-8"?>
<catalog>
  <cd>
    <title>Empire Burlesque</title>
    <artist>Bob Dylan</artist>
    <country>USA</country>
    <company>Columbia</company>
    <price>10.90</price>
    <year>1985</year>
  </cd>
  <cd>
    <title>Romanza</title>
    <artist>Andrea Bocelli</artist>
    <country>EU</country>
    <company>Polydor</company>
    <price>10.80</price>
    <year>1996</year>
  </cd>
  <cd>
    <title>When a man loves a woman</title>
    <artist>Percy Sledge</artist>
    <country>USA</country>
    <company>Atlantic</company>
    <price>8.70</price>
    <year>1987</year>
  </cd>
  <cd>
    <title>Black angel</title>
    <artist>Savage Rose</artist>
    <country>EU</country>
    <company>Mega</company>
    <price>10.90</price>
    <year>1995</year>
  </cd>
  <cd>
    <title>1999 Grammy Nominees</title>
    <artist>Many</artist>
    <country>USA</country>
    <company>Grammy</company>
    <price>10.20</price>
    <year>1999</year>
  </cd>
  <cd>
    <title>For the good times</title>
    <artist>Kenny Rogers</artist>
    <country>UK</country>
    <company>Mucik Master</company>
    <price>8.70</price>
    <year>1995</year>
  </cd>
  <cd>
    <title>Big Willie style</title>
    <artist>Will Smith</artist>
    <country>USA</country>
    <company>Columbia</company>
    <price>9.90</price>
    <year>1997</year>
  </cd>
  
</catalog>


<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html> 
<body>
  <h2>My CD Collection</h2>
  <table border="1">
    <tr bgcolor="#9acd32">
      <th style="text-align:left">Title</th>
      <th style="text-align:left">Artist</th>
    </tr>
    <xsl:for-each select="catalog/cd">
    <tr>
      <td><xsl:value-of select="title"/></td>
      <td><xsl:value-of select="artist"/></td>
    </tr>
    </xsl:for-each>
  </table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

xml 與 xsd(Schema )[知識擴展]
<?xml version="1.0" encoding="ISO-8859-1"?>

<persons xmlns="http://www.w3schools.com"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.mynamespace.com children.xsd http://www.w3schools.com family.xsd">
    
    <person>
        <firstname>Hege</firstname>
        <lastname>Refsnes</lastname>
        <children xmlns="http://www.mynamespace.com">
            <childname>Cecilie</childname>
        </children>
    </person>
    
    <person>
        <firstname>Stale</firstname>
        <lastname>Refsnes</lastname>
    </person>
    
</persons>
<?xml version="1.0" encoding="ISO-8859-1"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://www.w3schools.com"
    xmlns="http://www.w3schools.com"
    elementFormDefault="qualified">


<xs:element name="persons">
        
        <xs:complexType>          
            <xs:sequence>   
                <xs:element ref="person" minOccurs="1" maxOccurs="unbounded"/>               
            </xs:sequence>     
        </xs:complexType>
        
</xs:element>


<xs:element name="person">
    <xs:complexType>
        <xs:sequence>
            <xs:element name="firstname" type="xs:string"/>
            <xs:element name="lastname" type="xs:string"/>
            <xs:any minOccurs="0"/>
        </xs:sequence>
    </xs:complexType>
</xs:element>

</xs:schema>
<?xml version="1.0" encoding="ISO-8859-1"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://www.mynamespace.com"
    xmlns="http://www.mynamespace.com"
    elementFormDefault="qualified">
    
    <xs:element name="children">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="childname" type="xs:string"
                    maxOccurs="unbounded"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    
</xs:schema>
xml 與 xsd(schema)(添加屬性 )[知識擴展]
<?xml version="1.0" encoding="UTF-8"?>
<articles xmlns="http://www.w3schools.com"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.w3schools.com News.xsd" >
    
    <article>
        <Title>蝗災肆虐 數十年罕見:東非多國遭大量蝗蟲入侵</Title>
        <Date>2002-02-14T17:45:10</Date>
        <linkexplain link="http://www.chinanews.com/gj/shipin/cns/2020/02-11/news847505.shtml">資料視頻:一天吞噬3400萬人的糧食!沙漠蝗蟲羣入侵非洲之角來源:中國新聞網</linkexplain>
        <content1> 中新網2月14日電 據“中央社”報道,位於東非的埃塞俄比亞南部、肯尼亞部分地區正遭受蝗災入侵,蝗蟲數量龐大數十年僅見,眼見數十億蝗蟲大軍逼進當地糧倉,卻只有零星8架飛機可噴藥,讓專家急得像熱鍋上的螞蟻。</content1>
        <image src="/Users/atom-g/XML/exam/測試1/photo_example.jpg" />
        <content2>資料圖:當地時間2020年1月21日,在肯尼亞Archers Post附近的拉里索羅村,蝗蟲飛過灌木叢。
              《華盛頓郵報》報道稱,這批蝗蟲遠看像是滾滾濃煙,接近後這數十億蝗蟲又像難以計數的雨點。
              據報道,在飽經戰亂的也門與索馬里,政府控制區外的地帶成了蝗蟲大軍的溫牀,與氣候變遷導致的印度洋厄爾尼諾現象帶來季節異常的降雨,讓這個區域更利蝗蟲滋長。蝗蟲吞噬農田、市場無物可賣、牲口無物可吃,非洲東部已有約1900萬人面臨高度食物短缺危機。
              在埃塞俄比亞首都亞的斯亞貝巴的聯合國糧農組織害蟲防控專家巴耶說,“我們唯一的選項就是把它們全殺光。”
              埃塞俄比亞北部1954年也遇過程度類似的蝗災,當時蝗蟲摧毀近乎當地百分之百的綠葉植被,加上又遇乾旱,發生長達一年饑荒。
              儘管科技已有進步,但控制蝗害仍不樂觀,因爲大量的蝗蟲在也門與索馬里沿岸平原的沙地孵化,埃塞俄比亞卻只有3架可用的飛機能噴藥,肯尼亞也只有5架。蝗蟲大軍正逐日進逼位於東非大裂谷的埃塞俄比亞糧倉。
              空中噴藥的最佳時機是蝗蟲大軍還停在地面,由於蝗蟲是冷血生物,在白天變暖前幾無活動力,因此清晨是最佳噴藥時機;可不幸的是,頻繁的晨雨多次阻礙空中噴藥,等飛機升空時,蝗蟲大軍早已在空中。
              埃塞俄比亞政府僱傭私人公司的噴藥飛行員說,“它們靠上升氣流飛達約914米高,數量多到能阻塞飛機進氣口,其實這樣很危險。”近期某日,當這名飛行員結束噴藥任務後,飛機全身已滿是蟲擊的黏液,多到連擋風玻璃都已看不清楚。
              聯合國表示,應立即投入7600萬美元增強當地空中噴藥能力。
            巴耶說,“2020可謂蝗害之年;我們不能坐以待斃,否則整個區域都會被蝗災吞沒,就會變成一個很大、很大的危機。”
        </content2>
        <Author>編輯:李弘宇</Author>  
    </article>   
</articles>

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"  
    targetNamespace="http://www.w3schools.com"
    xmlns="http://www.w3schools.com"
    elementFormDefault="qualified"> 

<xs:element name="articles">
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="article" minOccurs="1" maxOccurs="unbounded"/>
            </xs:sequence>
        </xs:complexType>
</xs:element>
    
    <xs:element name="article">
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="Title" minOccurs="1" maxOccurs="1"/>
                <xs:element ref="Date" minOccurs="1" maxOccurs="1"/>
                <xs:element ref="linkexplain" minOccurs="1" maxOccurs="1"/>
                <xs:element ref="content1" minOccurs="0" maxOccurs="1"/>
                <xs:element ref="image" minOccurs="0" maxOccurs="1"/>
                <xs:element ref="content2" minOccurs="1" maxOccurs="1"/>
                <xs:element ref="Author" minOccurs="1" maxOccurs="1"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    
    <xs:element name="Title" type="xs:string"/>
    <xs:element name="Date" type="xs:dateTime"/>
    <xs:element name="linkexplain">
        <xs:complexType>
           <xs:simpleContent>
            <xs:extension base="xs:string">
             <xs:attribute name="link" type="xs:anyURI"/>
            </xs:extension>
           </xs:simpleContent>
        </xs:complexType>
    </xs:element>
    <xs:element name="content1" type="xs:string"/>
    <xs:element name="image">
        <xs:complexType>
            <xs:attribute name="src" type="xs:anyURI"/>
        </xs:complexType>
    </xs:element>
    <xs:element name="content2" type="xs:string"/>
    <xs:element name="Author" type="xs:string"/>

</xs:schema>

xml 與 xsl(添加圖片 )[知識擴展]
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="pictest.xsl"?>
<image>
    <image-clear1 src="/Users/atom-g/XML/exam/測試1/photo_example.jpg" width="555" height="440"/>
</image>
<?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"
    exclude-result-prefixes="xs"
    version="1.0">
    
    <xsl:template match="image">
        <img>
            <xsl:attribute name="src"><xsl:value-of select="image-clear1/@src"/></xsl:attribute>
            <xsl:attribute name="width"><xsl:value-of select="image-clear1/@width"/></xsl:attribute>
            <xsl:attribute name="height"><xsl:value-of select="image-clear1/@height"/></xsl:attribute>
        </img>
    </xsl:template>
    
</xsl:stylesheet>

xml轉PDF

1 製作一個xml實例

<?xml version="1.0" encoding="UTF-8"?>
    
<article>
    
        <Title>蝗災肆虐 數十年罕見:東非多國遭大量蝗蟲入侵</Title>
        <Date>2002-02-14T17:45:10</Date>
        <linkexplain link="http://www.chinanews.com/gj/shipin/cns/2020/02-11/news847505.shtml">資料視頻:一天吞噬3400萬人的糧食!沙漠蝗蟲羣入侵非洲之角來源:中國新聞網</linkexplain>
        <content1> 中新網2月14日電 據“中央社”報道,位於東非的埃塞俄比亞南部、肯尼亞部分地區正遭受蝗災入侵,蝗蟲數量龐大數十年僅見,眼見數十億蝗蟲大軍逼進當地糧倉,卻只有零星8架飛機可噴藥,讓專家急得像熱鍋上的螞蟻。</content1>
        <image>
            <image_1 src="/Users/atom-g/XML/exam/測試2/photo_example.jpg" width="555" height="440" />
        </image>
        <content2>資料圖:當地時間2020年1月21日,在肯尼亞Archers Post附近的拉里索羅村,蝗蟲飛過灌木叢。
              《華盛頓郵報》報道稱,這批蝗蟲遠看像是滾滾濃煙,接近後這數十億蝗蟲又像難以計數的雨點。
              據報道,在飽經戰亂的也門與索馬里,政府控制區外的地帶成了蝗蟲大軍的溫牀,與氣候變遷導致的印度洋厄爾尼諾現象帶來季節異常的降雨,讓這個區域更利蝗蟲滋長。蝗蟲吞噬農田、市場無物可賣、牲口無物可吃,非洲東部已有約1900萬人面臨高度食物短缺危機。
              在埃塞俄比亞首都亞的斯亞貝巴的聯合國糧農組織害蟲防控專家巴耶說,“我們唯一的選項就是把它們全殺光。”
              埃塞俄比亞北部1954年也遇過程度類似的蝗災,當時蝗蟲摧毀近乎當地百分之百的綠葉植被,加上又遇乾旱,發生長達一年饑荒。
              儘管科技已有進步,但控制蝗害仍不樂觀,因爲大量的蝗蟲在也門與索馬里沿岸平原的沙地孵化,埃塞俄比亞卻只有3架可用的飛機能噴藥,肯尼亞也只有5架。蝗蟲大軍正逐日進逼位於東非大裂谷的埃塞俄比亞糧倉。
              空中噴藥的最佳時機是蝗蟲大軍還停在地面,由於蝗蟲是冷血生物,在白天變暖前幾無活動力,因此清晨是最佳噴藥時機;可不幸的是,頻繁的晨雨多次阻礙空中噴藥,等飛機升空時,蝗蟲大軍早已在空中。
              埃塞俄比亞政府僱傭私人公司的噴藥飛行員說,“它們靠上升氣流飛達約914米高,數量多到能阻塞飛機進氣口,其實這樣很危險。”近期某日,當這名飛行員結束噴藥任務後,飛機全身已滿是蟲擊的黏液,多到連擋風玻璃都已看不清楚。
              聯合國表示,應立即投入7600萬美元增強當地空中噴藥能力。
            巴耶說,“2020可謂蝗害之年;我們不能坐以待斃,否則整個區域都會被蝗災吞沒,就會變成一個很大、很大的危機。”
        </content2>
        <Author>編輯:李弘宇</Author>
    
</article>
    

2 製作一個XSLT(fo)式樣單

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xslt="http://www.w3.org/1999/XSL/Transform" 
    xmlns:fo="http://www.w3.org/1999/XSL/Format" version="1.0">

    
    <!--  Template for root element 'News'  -->
    <xsl:template match="article">
        <fo:root font-family="SimSun" xmlns:fo="http://www.w3.org/1999/XSL/Format">
            <fo:layout-master-set>
                <fo:simple-page-master master-name="one" page-height="12cm" page-width="21cm" margin-left="0cm" margin-right="0cm">
                    <fo:region-body/>
                </fo:simple-page-master>
            </fo:layout-master-set>
            
            <fo:page-sequence master-reference="one">
                <fo:flow flow-name="xsl-region-body" font-size="10pt" line-height="18pt">
                   
                    <xsl:apply-templates select="Title"/>
                    <fo:block text-align="justify" margin-left="0cm" margin-right="0cm" >
                        <xsl:apply-templates select="Date"/>
                        
                        <xslt:apply-templates select="linkexplain"/>
                        
                        <xslt:apply-templates select="content1"/>
                        
                        <xslt:apply-templates select="image"/>
                        
                        <xslt:apply-templates select="content2"/> 
                    </fo:block>                   
                    <xslt:apply-templates select="Author"/>           
                
                </fo:flow>
            </fo:page-sequence>
            
        </fo:root>
    </xsl:template>
    
    <!--  Template for element type 'Title'  -->
    <xsl:template match="Title">
        <fo:block text-align="center" font-size="24pt" font-weight="bold" color="black" line-height="28pt" >
            <xsl:apply-templates/>
        </fo:block>
    </xsl:template>
    
    <!--  Template for element type 'Date| linkexplain'  -->
    <xslt:template match="Date ">
        <fo:inline font-size="7pt" margin-left="2cm">
            <xslt:apply-templates/>
        </fo:inline>
    </xslt:template>

    <xslt:template match="linkexplain ">
        <fo:block text-align="center">
        <fo:inline font-size="7pt" margin-left="1cm" >
            <xslt:apply-templates/>
        </fo:inline>
        </fo:block>
    </xslt:template>
    
    <!--  Template for element type 'content1'  -->
    <xslt:template match="content1">
        <fo:block  margin-left="0cm" margin-right="0cm">
            <fo:inline font-weight="bold">
            <xslt:apply-templates/>
            </fo:inline>
        </fo:block>
    </xslt:template>
    
    <!--  Template for element type 'image'  -->
    <xsl:template match="image">
        <fo:block margin-left="5cm" margin-right="0cm" >
            <fo:external-graphic src="/Users/atom-g/XML/exam/測試2/photo_example.jpg"/>
        </fo:block>
    </xsl:template>
    
    <!--  Template for element type 'content2'  -->
    <xslt:template match="content2">
        <fo:block text-align="center"  margin-left="0cm" margin-right="1cm" margin-top="2com">
            <fo:inline font-weight="bold">
                <xslt:apply-templates/>
            </fo:inline>
        </fo:block>
    </xslt:template>
    
    <xslt:template match="Author">
        <fo:block text-align="right" margin-top="1com">
            <xslt:apply-templates/>
        </fo:block>
    </xslt:template>
    
</xsl:stylesheet>

3 將XML文檔通過XSLT轉換成XSL-FO

用此命令去生成fo:
xsltproc -o /Users/atom-g/XML/exam/測試2/News_t2.fo /Users/atom-g/XML/exam/測試2/News_xslt.xsl /Users/atom-g/XML/exam/測試2/News.xml

4 採用FOP將上述文檔轉換成PDF格式
這裏兵分兩路,兩種辦法但是殊途同歸
方法1 - 命令行

//下載fop  //會下載到/usr/local/Cellar(這裏是隱藏文件,記得用Command + Shift + . 使其現身)
1	brew install fop	
2   cmd輸入 fop 		//看看你想如何命令它把	
3	fop -xml /Users/atom-g/XML/exam/測試2/News.xml -xsl /Users/atom-g/XML/exam/測試2/News_xslt.xsl -pdf /Users/atom-g/XML/exam/測試2/News_readonly.pdf	//輸出(英文)

在這裏插入圖片描述
在這裏插入圖片描述
這裏需要注意,用TEAM-AG配置好的獨家配方包
在這裏插入圖片描述

//下載fop  //會下載到/usr/local/Cellar(這裏是隱藏文件,記得用Command + Shift + . 使其現身)
1	brew install fop	
2   cmd輸入 fop 		         //看看你想如何命令它把	

****這條指令是要求 fop 去找 fop.xconf 讀那裏面的配置信息 通過fop.xconf裏的配置信息輸出****
3	fop -c /usr/local/Cellar/fop/2.4_2/libexec/fop/conf/fop.xconf /Users/atom-g/XML/exam/測試2/News.fo -pdf /Users/atom-g/XML/exam/測試2/ReadOnly_cmd.pdf     //輸出(中文)

方法2 - java
在這裏插入圖片描述
項目完整包我已放在上傳文件中 名爲:xml轉PDF_完整項目_CodingPark

package com.cisetech.put.utils.fop;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;

import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.stream.StreamSource;

import org.apache.avalon.framework.logger.ConsoleLogger;
import org.apache.avalon.framework.logger.Logger;
import org.apache.fop.apps.Fop;
import org.apache.fop.apps.FopFactory;
import org.apache.fop.apps.MimeConstants;

/**
 * FopReport
 * @author bin.yin 2012/12/23
 */
public class FopReport {
	private static Logger log = new ConsoleLogger(ConsoleLogger.LEVEL_DEBUG);
	// Step 1: Construct a FopFactory
	private static final FopFactory fopFactory = FopFactory.newInstance();

	/**
	 * 根據xsl模板及xml數據文件生成pdf
	 * @param xsltFile xsl模板
	 * @param xmlFile xml數據文件
	 * @return ReportData
	 * @throws Exception
	 * @author TEAM-AG
	 */

	public static ReportData createReport(String xsltFile, String xmlFile) throws Exception {
		ReportData reportData = new ReportData();
		reportData.setContentType("application/pdf");
		fopFactory.setUserConfig("conf/fop.xml");

		// Step 2: Set up output stream.
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		try {
			// Step 3: Construct fop with desired output format
			Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, out);

			// Step 4: Setup XSLT using identity transformer
			TransformerFactory factory = TransformerFactory.newInstance();
			Transformer transformer = factory.newTransformer(new StreamSource(new File(xsltFile)));

			// Step 5: Setup input and output for XSLT transformation
			Source src = new StreamSource(new File(xmlFile));
			// Source src = new StreamSource(new StringReader(myString));

			// Step 6: Resulting SAX events (the generated FO) must be piped through to FOP
			Result res = new SAXResult(fop.getDefaultHandler());

			// Step 7: Start XSLT transformation and FOP processing
			transformer.transform(src, res);

			reportData.setData(out.toByteArray());
		} catch(Exception e) {
			throw e;
		} finally {
			out.close();
		}
		return reportData;
	}

	/**
	 * 根據xsl模板及xml字節數組生成pdf
	 * @param xsltFile xsl模板
	 * @param bXmlData xml字節數組 eg. StringBuffer buf = new StringBuffer(); buf.getBytes("UTF-8");
	 * @return ReportData
	 * @throws Exception
	 * @author TEAM-AG
	 */

	public static ReportData createReport(String xsltFile, byte[] bXmlData) throws Exception {
		ReportData reportData = new ReportData();
		try {
			// convert xml bytes to a temp file
			File xmlFile = File.createTempFile("FOP", ".tmp");
			FileOutputStream fos = new FileOutputStream(xmlFile);
			fos.write(bXmlData);
			fos.close();
			
			reportData = createReport(xsltFile, xmlFile.getAbsolutePath());
			// delete temp file
			xmlFile.delete();
		} catch (Exception e) {
			throw e;
		}
		return reportData;
	}

	public static void main(String[] args) {
		long t0 = System.currentTimeMillis();
		try {
			StringBuffer buf = new StringBuffer();
			buf.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
			buf.append("<article>");
			buf.append("    <Title>蝗災肆虐 數十年罕見:東非多國遭大量蝗蟲入侵</Title>");
			buf.append("        <Date>   2002-02-14T17:45:10</Date>");
			buf.append("        <linkexplain link=\"http://www.chinanews.com/gj/shipin/cns/2020/02-11/news847505.shtml\">資料視頻:一天吞噬3400萬人的糧食!沙漠蝗蟲羣入侵非洲之角來源:中國新聞網</linkexplain>");
			buf.append("         <content1> 中新網2月14日電 據“中央社”報道,位於東非的埃塞俄比亞南部、肯尼亞部分地區正遭受蝗災入侵,蝗蟲數量龐大數十年僅見,眼見數十億蝗蟲大軍逼進當地糧倉,卻只有零星8架飛機可噴藥,讓專家急得像熱鍋上的螞蟻。</content1>");
			buf.append("      <image>");
			buf.append("    <image_1 src=\"/Users/atom-g/XML/exam/測試2/photo_example.jpg\" width=\"555\" height=\"440\" />");
			buf.append("        </image>");
			buf.append("            <content2>資料圖:當地時間2020年1月21日,在肯尼亞Archers Post附近的拉里索羅村,蝗蟲飛過灌木叢。\n" +
					"              《華盛頓郵報》報道稱,這批蝗蟲遠看像是滾滾濃煙,接近後這數十億蝗蟲又像難以計數的雨點。\n" +
					"              據報道,在飽經戰亂的也門與索馬里,政府控制區外的地帶成了蝗蟲大軍的溫牀,與氣候變遷導致的印度洋厄爾尼諾現象帶來季節異常的降雨,讓這個區域更利蝗蟲滋長。蝗蟲吞噬農田、市場無物可賣、牲口無物可吃,非洲東部已有約1900萬人面臨高度食物短缺危機。\n" +
					"              在埃塞俄比亞首都亞的斯亞貝巴的聯合國糧農組織害蟲防控專家巴耶說,“我們唯一的選項就是把它們全殺光。”\n" +
					"              埃塞俄比亞北部1954年也遇過程度類似的蝗災,當時蝗蟲摧毀近乎當地百分之百的綠葉植被,加上又遇乾旱,發生長達一年饑荒。\n" +
					"              儘管科技已有進步,但控制蝗害仍不樂觀,因爲大量的蝗蟲在也門與索馬里沿岸平原的沙地孵化,埃塞俄比亞卻只有3架可用的飛機能噴藥,肯尼亞也只有5架。蝗蟲大軍正逐日進逼位於東非大裂谷的埃塞俄比亞糧倉。\n" +
					"              空中噴藥的最佳時機是蝗蟲大軍還停在地面,由於蝗蟲是冷血生物,在白天變暖前幾無活動力,因此清晨是最佳噴藥時機;可不幸的是,頻繁的晨雨多次阻礙空中噴藥,等飛機升空時,蝗蟲大軍早已在空中。\n" +
					"              埃塞俄比亞政府僱傭私人公司的噴藥飛行員說,“它們靠上升氣流飛達約914米高,數量多到能阻塞飛機進氣口,其實這樣很危險。”近期某日,當這名飛行員結束噴藥任務後,飛機全身已滿是蟲擊的黏液,多到連擋風玻璃都已看不清楚。\n" +
					"              聯合國表示,應立即投入7600萬美元增強當地空中噴藥能力。\n" +
					"            巴耶說,“2020可謂蝗害之年;我們不能坐以待斃,否則整個區域都會被蝗災吞沒,就會變成一個很大、很大的危機。”\n" +
					"        </content2>");
			buf.append("               <Author>編輯:李弘宇</Author>");
			buf.append("                </article>");


			long t = System.currentTimeMillis();
			System.out.println("檢查點1");
//			ReportData data = FopReport.createReport("report/sample/News_xslt.xsl", buf.toString().getBytes("UTF-8"));
			ReportData data = FopReport.createReport("report/sample/News_xslt.xsl", "report/sample/News.xml");
			System.out.println("檢查點2");
			long t1 = System.currentTimeMillis();
			log.debug("time:" + (t1 - t));
			FileOutputStream fos = new FileOutputStream("/Users/atom-g/XML/exam/測試2/ReadOnly.pdf");
			fos.write(data.getData());
			fos.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		log.debug("use time:" + (System.currentTimeMillis() - t0));
	}
}

package com.cisetech.put.utils.fop;

import java.io.Serializable;

/**
 * <p>Title: </p>
 * <p>Description: </p>
 * @author TEAM-AG
 * @version 1.0
 */
public class ReportData implements Serializable {
	private static final long serialVersionUID = -2722248902864797698L;

	private byte[] mbData = null;
	private String msContentType = null;

	public byte[] getData() {
		return mbData;
	}
	public void setData(byte[] pData) {
		mbData = pData;
	}
	public String getContentType() {
		return msContentType;
	}
	public void setContentType(String pContentType) {
		msContentType = pContentType;
	}
}

5 總結與思考

1 中文亂碼問題 xsl(fo) 中大有學問
在這裏插入圖片描述
在這裏插入圖片描述
結果展示:左java輸出|右cmd輸出
在這裏插入圖片描述
2 相關文章推薦

http://www.linkwerk.com/pub/xml/invitation/xml2pdf/ 【相關案例】
https://blog.csdn.net/resuce/article/details/80215678 【相關案例】
https://blog.csdn.net/QQ694885382/article/details/81044007 【如何使用相對路徑,./、…/、…/…/】

3 特別鳴謝

ZhanWen
BaiFeng
ZhaoXu
HuChuan

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章