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

在这里插入图片描述

原创文章 35 获赞 22 访问量 2984

猜你喜欢

转载自blog.csdn.net/weixin_38411989/article/details/105546542